Testing


I never really used a debugger until I did Java. Before that I did what was called “PHP Debugging” which is littering your code with print statements until you figure out what you need to know, then going back and making sure you deleted them! I sometimes would put a unique string like

print “QWE” . $myawesomevar

Or something like that, then going back and searching your code for QWE (just picked something that was easy to type!). But all that gets rather annoying. They might have nice debuggers for PHP now, I haven’t really done php in 4-5 years. I really didn’t understand the power of breakpoints until I did java and I thought that was pretty cool. Now that I do all ruby, I sort of miss eclipse (I didn’t actually think I’d ever say that…) since all I use right now is textmate and vi which don’t have the built debugger support that eclipse does. Some of the newer ruby editors might, I haven’t spent any research on them.

I found ruby-debug and it works great! You can set a breakpoint and then climb inside your application and peek around and see what is going on. I’ve done this in controllers and even in test mode.

If you use passenger, you can still use it but its a little tricky to setup. This blog post from duckpunching.com has some neat tips and a rake task to make it easier. Be sure to start the rdebug -c from the console after you have set a breakpoint and reloaded your page.

If you are using passenger, you can’t use the irb command inside of the ruby-debug console, but I found that most of the time just being able to poke around the variable space inside my app has been enough for me to understand what is going on.

There are quite a few commands available in the debug console, but these are the ones I’ve used:

help - view the list of commands
l list - this shows context around the current line the debugger is on
n next - moves to the next line
p print - print a variable
irb jump to console - I dont use this very often and it doesn’t work if you are using passenger
c cont - continue to end of breakpoint or end of page load, after I have seen what I want to see I do this to get out of the console

Resources

Anyways, hope some of you find it useful and happy debugging :)

Update: I wrote this in preparation for a short talk at AustinOnRails while giving the talk, the group had some suggestions:

put in a ~/.rdebugrc

set autoeval
set autolist

autolist - will run list command when you enter
autoeval - will eval each line, so instead of “eval @profile” to get it to print, it will automatically eval

doing m [object] can show methods in a nice table format. Thats cool, i have often gone to irb and did String.methods.sort but that is kinda hard to read.

Anyways, good stuff!

I’ve have been pondering in the past 6 months - How do I get better at programing? What is the best way? do I need more books? At my current company, we whole heartedly engage in peer reviews, nothing gets checked in the repository without at least one person going over it. In that process, i’ve learned more about coding then I could from 10 books. I used to be a book fiend. I had about 10 books on every subject. Did I learn? yeah, some! But I think I’ve learned more from doing and practice. Practice, practice, practice! When the Chicago Ruby User Group offered this book in exchange for a review, I jumped at the chance.

“Refactoring in Ruby” written by William C. Wake and Kevin Rutherford.
Published by Addison-Wesley

“Refactoring in Ruby” is more like a “workbook” then a “how to write awesome code” book. If you download the code from github http://github.com/kevinrutherford/rrwb-code you have tests already written for the exercises.

The book is arranged in three parts, The Art of Refactoring, Code Smells, and Programs to Refactor.

There are explanations of “code smells” which are one characteristic of code that could be improved. Some of them are long parameter lists, unnecessarily complex, global variable, feature envy sections, etc. One thing I find interesting is the “How did it get this way?” section. It gives some insight into the thought process and reasoning behind the smell. I think this is good, as programmers our ego may be rather miffed to hear “This code stinks” but with some reasoning, it makes the pain less and I think firms up in our minds when this happens again, to do it this other way. I always want to know why when someone says I could do such and such thing better.

In addition to the code smell examples there are three programs to refactor in the end of the book. In a conversational tone, it walks through and gives some hints on what needs refactoring. Its almost as if you had a pair programming buddy working with you and identifying in small chunks what can be improved. This is definitely something I want to work through more carefully.

What I find odd, is that not all the code smells have code examples. The inspiration for the book I think is the Martin Fowler book “Refactoring Improving the design of Existing Code” which has examples for every code smell. Maybe Ruby smells less than Java? Or those fixes are really trivial? I don’t know. Overall, this is a great book and is certainly worth the price and investment and you will be a better programmer because of it!

There are explanations of “code smells” which are one characteristic of code that could be improved. Some of them are long parameter lists, unnecessarily complex, global variable, feature envy sections, etc. One thing I find interesting is the “How did it get this way?” section. It gives some insight into the thought process and reasoning behind the smell. I think this is good, as programmers our ego may be rather miffed to hear “This code stinks” but with some reasoning, it makes the pain less and I think firms up in our minds when this happens again, to do it this other way. I always want to know why when someone says I could do such and such thing better.

In addition to the code smell examples there are three programs to refactor in the end of the book. In a conversational tone, it walks through and gives some hints on what needs refactoring. Its almost as if you had a pair programming buddy working with you and identifying in small chunks what can be improved. This is definitely something I want to work through more carefully.

What I find odd, is that not all the code smells have code examples. The inspiration for the book I think is the Martin Fowler book “Refactoring Improving the design of Existing Code” which has examples for every code smell. Maybe Ruby smells less than Java? Or those fixes are really trivial? I don’t know. Overall, this is a great book and is certainly worth the price and investment and you will be a better programmer because of it!

This book is still in beta, but so far… I love it!

Chapter 1 is a very brief overview of RSpec and Cucumber and in Chapter 2 you are shown some examples. This is Real Code That Works! You can type it in and run. That is awesome, I was so excited last night that I almost couldn’t stop and go to sleep (Doc tells me to get more sleep. BAH!). I’ve done RSpec on a fairly large project before, a few years ago. I had seen some presentation at the Chirb meetings about some kind of testing involving Stories and Scenarios. It was interesting then… I just wasn’t sure how you can translate that into code. Now I see, it looks like this method has matured to the point where it is viable. Cucumber is only version 0.3.11 at this time but hey! Its cool, its tight, its gonna take off!

Chapter 3 - Starting off with a game example! WAY TO GO! Nothing more uninteresting than Yet Another Bank Account or Blog example. This is totally awesome. Its a very conversational at first, as you are learning how to apply the “Story” concept to the need. Once the planning is out of the way…. its time to code!

Chapter 4 - Cucumber, Writing steps to the stories

Chapter 5 - RSpec, writing rspec tests

Its great to see code that you can type in an run and its kinda fun, it a game! what isn’t fun about that! Great book so far Dave Chelimsky, Dave Astels, Zach Dennis, Aslak Hellesoy, Bryan Helmkamp and Dan North. Right on! Looking forward to the rest :)

I’ve been kinda on a rails spree lately, I guess I’ve had some free time and also redoing a rails 1.1.6 project (and was noob then and no clue of what I was doing) and updating it to use REST.

I got Geoffrey Grosenbach PeepCode’s REST Tutorial, which is very awesome and well worth the 9 bucks. Its over an hour long! I also got the RJS Tutorial which is also awesome. I can’t wait till payday to get the $40 pack so I can get some more! There’s just something about SEEING something work that makes it stick sometimes.

Also I spent some time on Railscasts which features a ton of short demos on rails topics. Very cool. In particular i liked Testing Without Fixtures which is cool because sometimes fixtures are a PITA!

When watching one of the PeepCode screencasts I saw him using “autotest” .. a cool toy which I must have too! I searched for it and found this posting on his blog. Now I’m autotesting all the time :) It basically monitors your rails site and runs the test everytime you change your code.

I’ve been using e-TextEditor and slowly learning the shortcuts. I love the font that was on PeepCode’s screen cast and found a link on the PeepCode FAQ where I can download it. For Free! And it mentioned the name of the theme used in Textmate — which happened to be the one I had found in e-Text-Editor and was using. No wonder I liked it! I also used this font in my Putty settings and changed the awful default colors (esp that dark blue! hard to see!). e-TextEditor is in Beta but its in great shape and i was so happy to see a “close all tabs” feature put into the latest build. I’ll be ecstatic when they make a linux version.

Any one know, does there exist a TestSimple/More (from Perl) for Java like the module for Perl?

whats that you say? I wrote about TestMore in Perl and PHP Here and here also!

I did a quick scan with google didn't give me much hope. So I wrote this quickly on the train this morning, since I can't hardly stand to program in any language without a TestMore like implementation.. (I know there's JUnit, and I'ved used it before, but its alot of overhead.. I just needed some quick tests!)

Class: (not making any claim this is the best or greatest way, and not 100% TAP protocol)

JAVA:
  1. package com.myawesomesite.util;
  2.  
  3. public class TestSimple {
  4.  
  5.  private int testCount;
  6.  
  7.  public TestSimple() {
  8.   this.testCount = 0;
  9.  }
  10.  
  11.  public void ok(boolean truth, String message) {
  12.   this.testCount++;
  13.   System.out.println( (truth ? "ok " : "not ok ")
  14.                       + this.testCount + " - "
  15.                       + message);
  16.  }

Usage:

JAVA:
  1. package com.myawesomesite.java;
  2.  
  3. import com.myawesomesite.java.*;
  4. import com.myawesomesite.util.TestSimple;
  5.  
  6. public class TestAnimal {
  7.  
  8.  public static void main(String[] args) {
  9.   TestSimple test = new TestSimple();
  10.  
  11.   Dog bob = new Dog();
  12.  
  13.   bob.setColor("green");
  14.   bob.setCollarSize(10);
  15.  
  16.   test.ok(bob.getColor() == "green", "bob's color is green");
  17.   test.ok(bob.getCollarSize() == 10,"bob's collar size is 10");
  18.   test.ok(bob.getCollarSize() == 0,"bob's collar size 0");
  19.  
  20.  
  21.  }
  22.  
  23. }

output is:

ok 1 - bob's color is green
ok 2 - bob's collar size is 10
not ok 3 - bob's collar size is 0

Update: Chris Shiflett posted an informative reponse on Test-More for PHP and testing in general

I started responding to the comment to my last post, then realized it was going to be long. So I put it in a post.

Thanks Damien Gilles, I have looked at that. Problem is, I have some resistance at work to using outside code. So I would need to work up a case for it beforehand and analyize it.

For really simple tests, this sort of testing (my friend Keith calls it Sanity testing) works fine. I don't really see the need to use a Unit Test framework. I have used PHPUnit before and it works fine, but ends up being just more typing (I think, but I'll try it and compare my results).

Here's an example of how I used it..

include_once("config.php");
include_once("User_Model.class.php");

$t = new Test_Simple(array("tests" => 20, "eol"=>" n"));

connect_db();
test_setup();

// Test object get/set methods
$user = new User_Model();
$user->setUserName("jdoe");
$user->setRealName("John Doe Test");
$user->setEmail("john@doe.com");
$user->setPermission("1");

// test true values
$t->ok( $user->getRealName()   == "John Doe Test", "get RealName" );
$t->ok( $user->getUserName()   == "jdoe", "get UserName" );
$t->ok( $user->getEmail()      == "john@doe.com", "get Email" );
$t->ok( $user->getPermission() == 1, "get Permission");

// test false values
$t->ok( $user->getRealName()   != "Susie Doe", "Not Realname Suzie Doe" );
$t->ok( $user->getUserName()   != "sdoe", "Not Username sdoe" );
$t->ok( $user->getEmail()      != "suz@doe.com", "Not email suz@doe.com" );
$t->ok( $user->getPermission() != 0, "Not Permission 0" );

// Save user
$saveResult = $user->save();
$t->ok( $saveResult == true, "Save was successful");

// Get ID of last user
$id = $user->id;

// clear object
$user = null;

// load user again and test again
$user = new User_Model($id);

// test true values
$t->ok( $user->getRealName()   == "John Doe Test", "get RealName after load" );
$t->ok( $user->getUserName()   == "jdoe", "get UserName after load" );
$t->ok( $user->getEmail()      == "john@doe.com", "get Email after load" );
$t->ok( $user->getPermission() == 1, "get Permission after load");

// change username
$user->setRealName("Mary Jane Test");
$user->setUserName("mjane");
$user->setEmail("mary@jane.com");
$user->setPermission("2");
$updateResult = $user->save();

// test true values
$t->ok( $updateResult == true, "Update was successful");
$t->ok( $user->id == $id, "ID stayed the same");
$t->ok( $user->getRealName()   == "Mary Jane Test", "get RealName after update" );
$t->ok( $user->getUserName()   == "mjane", "get UserName after update" );
$t->ok( $user->getEmail()      == "mary@jane.com", "get Email after update" );
$t->ok( $user->getPermission() == 2, "get Permission after update");

$deleteResult = $user->delete();
$t->ok( $deleteResult == true, "Delete was successful");

test_teardown();
$t->report();

// Clean up our mess before and after
function test_setup() {
connect_db();
$result = mysql_query("DELETE FROM users WHERE real_name like '%test%'");
}

function test_teardown() {
connect_db();
$result = mysql_query("DELETE FROM users WHERE real_name like '%test%'");
}

I did do a test_setup and test_teardown, similar to what you would have in a unit test. I only need to do this at the start of my "suite" and the end.

Of course, the main reason there's a test more (copied from Perl) for php is so you can use Perl to run the test suites. See this presentation by Geoffrey Young and Chris Shiflett on Power PHP Testing(tgz file) which, if you have a site with mixed PHP and Perl, would be a excellent way to test all your code with the same method.

My two loyal readers know I like testing. Some say I'm sick.

I'm writing a PHP class for a user, and then think.. oh gee, how do I know if this works?? oh I'll write a Test::Simple for PHP. Yes, I know there exists one already that uses the power of Perl to test PHP files, but I didn't have time to figure out how to set that up and probably won't be able to use perl anyways on the production system. I can't stand to have global variables, so I made a class. Uber simple. There's probably better ways to do it (I can imagine something much more elegant in PHP 5). But, what do you expect on a whim and 40 minutes...

Code:

// Nola's Wanna Be PHP Test Framework

class Test_Simple {
var $tests_to_run;
var $success_count;
var $failure_count;
var $test_count;

function Test_Simple($params) {
if (isset($_SERVER['HTTP_HOST'])) {
// we're on a server use a

$params['eol'] = "\ n "; //take out spaces, had to have them for this blog
}
$this->tests_to_run = $params["tests"];
$this->eol = empty($params['eol']) ? "\n" : $params['eol'] ;
$this->success_count = 0;
$this->failure_count = 0;
$this->test_count = 0;
print "1..{$this->tests_to_run}{$this->eol}";
}

function ok ($expression, $message) {
$this->test_count++;
if ($expression == false) {
print "not ";
$this->failure_count++;
} else {
$this->success_count++;
}
print "ok {$this->test_count} - $message" . $this->eol;
}

function report() {
print $this->eol;
if ($this->test_count tests_to_run) {
print "You ran {$this->success_count} out of "
. "{$this->tests_to_run} tests " . $this->eol;
} else {
print "Opps, looks like you meant to run {$this->tests_to_run} "
. "tests but ran {$this->test_count} instead" .$this->eol;
}
print "Success Rate: "
. (($this->success_count *100)/ $this->test_count)
. "%".$this->eol;
}

}

And.. I made some code to test itself..

$t = new Test_Simple(array("tests" => "4"));

$t->ok($t->test_count == 1, "one test run");
$t->ok($t->tests_to_run == 4, "running 4 tests");
$t->ok($t->eol == "\n", 'end of line is \n');
$t->ok(true, "its true!");
$t->ok(!false, "its not false");

$t->report();

I will probably make improvements upon this... suggestions? .. my test "report" is a bit more verbose than the standard Test::* in Perl.

I made it so you can run it with the php executable ... or with the web browser.

I tried to install Perl's class Apache::TestRunPHP but had a few problems getting it setup on windows. I think I need mod_perl installed on my Apache. I did find out that it takes a different approach than my simple class, and starts apache, runs tests, prints report and shuts down apache. Interesting. My tests I only intended to run individually (actually didn't know how TestRunPHP worked till after I wrote my class).

I posted an article about Selenium over at CodeSnipers.com .. check it out, its a very cool tool :)

Oh and fortune cookie for yesterday was:

He who enjoys doing and enjoys what he has done is happy.

I enjoy programming ... and looking back at some my of code I wrote -- I'm not happy. But I'm getting better everyday. :)

TEST!

Reduce Stress, Write a Test

Good article. Right now at work, I've put off some coding because i know it will be a pain to test. I've considered how to write unit tests for this, but since the whole page is procedural, I can't break it up. If I re-write it as a class or at least functions, I might be able to write a unit test for it.

I recently wrote a unit test for a simple logging class. I realized it didn't work the same on different versions of PHP, so I decided to make a unit test so I could see where it failed and where to fix.

Test test test!