I'm back from a week in the US and had a fabulous time celebrating the birthdays of two of my closest friends. Because I was on vacation, I did what any self-respecting geek would do: I taught someone automated testing.
The basic problem she had was the same problem I had when I got started in testing, but with an added twist. Many people like the idea of testing but they need that initial push. Just trying to test a 'Point' class or a log file parser sounds nice, but I keep hearing people say 'yeah, but that really doesn't apply to what I do. These people (like myself, years ago), need that first push. My friend's problem was like this, but with the added problem that the code she has to maintain is spaghetti with little modularity. Not an easy first task. It's basically programs with the following standard structure:
use some modules global variable declarations command line processing if/else chain and/or a loop construct a bunch of subs which refer to globals
This is such a common pattern in code that it makes me want to scream, but fortunately, it's not as hard to test as you might think.
You could use Expect (something I find painful), but if you're willing to give it a go, you can follow the standard strategy of just trying to load the program in a test program. Once you can get require_ok to pass, you can then start testing (though this really depends on how bad the code is). It works like this:
#!/usr/bin/perl use strict; use warnings; use Test::Most 'no_plan', 'die'; # stop some modules from loading $INC{'Some/TroubleSome/Module.pm'} = "loaded by $0"; require_ok 'bin/script_to_be_tested.pl'; { package Some::TroubleSome::Module; sub get_config { return { user => 'test', site => 'example.com', }; } } # override functions in other modules my ( $PROCESS_IN, $PROCESS_OUT ); { package Another::TroubleSome::Module; no warnings 'redefined'; sub process { $PROCESS_IN = shift; # fake results for unit testing $PROCESS_OUT = $results; } } # do some tests
With that, you then will likely need to take the core code in the program and wrap it in unless (caller) { ... }. With that, the block gets executed if called from the command line, but since caller will return true if loaded from the test program, the block won't get executed. This isn't a perfect setup, but neither is the mess of spaghetti that people who need this tend to have.
Which gets me down to my core point: I repeatedly find that people want to test, but don't know where to start. They need to learn how tests work before they can dig into their unique situations. That's why I'm toying with the idea of setting up a part-time test consultancy. Basically, I would be available on the occasional Saturday to lead a six-hour testing course, complete with exercises for programmers to work through. I already have some rough notes lined up for this and six hours would be easy to fill. The rough outline is something like this:
I do wonder, though, if there are enough programmers who care about testing and enough companies who understand its benefits to make this a worthwhile project to pursue. I want more people doing software testing. It will lower the company's costs and make the programmers turn out better code. This is important to me though I don't know if enough others feel the same way.
Note that if this project goes anywhere, it would strictly be a side project as I have no desire to leave the BBC. I love my job :)
Re:i would be interested
Ovid on 2008-06-02T07:07:56
Ah, cool. Good to know there's some chance of me pulling this off
:)
Re:Another common problem
Ovid on 2008-06-02T07:06:51
And there's a common testing anti-pattern associated with this. It's great to unit test the V and C, but many people will mock up so much of the Web framework when running integration tests that it's easy to test something which isn't exhibiting real behavior. It's a frustrating problem that can be difficult to break out of, once encountered.