9 March 2010

Code Quality Assurance

Last week I had the opportunity to give an one hour presentation on code quality assurance as part of the lecture on software testing to students of the Fachhochschule Technikum Wien. By "code quality assurance" I meant principles and techniques used by software developers to test their software and keep it free of bugs.

I believe that the most important ingredient of code quality is the mind-set of the developer. So I started with some slides about the Zero-Defect Mindset and Software Craftsmanship. Then I did a live demo performing the Prime Factors Code Kata to show the basics of unit testing, Test-Driven Development and regression testing. This was the main part of the presentation.

Break  FreeAfter that I explained the principles of code coverage, continuous integration, static code analysis and code reviews to the students. I mixed the theory (slides) with hands-on examples on the newly created Java code using EclEmma, Hudson, PMD and ReviewClipse.

Doing the demo was fun and the whole presentation was a success. For the demo I tried to stick to Scott Hanselman's Tips for a Successful Technical Presentation, esp. font size (Lucida Console, 16pt). Here is my "BigFonty" checklist:
  • Create a new, clean user profile for presentation only.
  • Set icons to large and number of colours to maximum.
  • Remove all icons from the desktop and choose a plain desktop background. I like to minimise all windows if I get lost between them.
  • Disable any screen saver and turn off energy saving. Otherwise they will definitely activate at the most annoying moment.
  • Set the command shell font to Lucida Console 16 point, bold, green on black. Have the default shell point to your main demo directory.
  • Clean up the browser, remove unnecessary tool bars and symbols. Unfortunately, at least in Windows, new users always have tons of crap on the desktop and in the browser.
  • Set the default browser page to empty or your main demo web-site.
  • Set the font size in your browser to very large and enable override of font sizes in styles. This is done in some accessibility sub-menu.
  • Use the browser in full screen mode (F11). You need all the space available for the large text.
  • Set the main font in your IDE to Lucida Console 16. In Eclipse it's enough to change the Text Font (in the Basic category in the sub-menu Colours and Fonts in Appearance).
  • Turn on line numbering in the IDE for quick reference of single lines.
  • Maximise the IDE and use a full screen source window whenever possible. In Eclipse just press Ctrl-M to maximise a view.
  • Start all applications like IDE or any server before the presentation. They may take some time.
(Download slides or source of Prime Factors Code Kata.)

14 February 2010

Turbo Pascal Prime Factors Kata

Wow Retro Recently I started performing the Prime Factors Kata. After playing with Java and Ruby I had the weird idea of performing it in every programming language I ever knew. Well, maybe not every - I don't plan to use 6502 or 80x86 assembler, that wouldn't be fun. But I already did it in BASIC. Going forward in time Turbo Pascal would be next. So it's time for another retro post ;-)

Where Is My TPUnit?
I couldn't find any unit testing framework for Turbo Pascal. The closest thing I could find was FPCUnit packaged with Free Pascal. Unfortunately it's not compatible with good old TP. So I had to roll my own. I started with some minimalist infrastructure.
TYPE TestCase = OBJECT
PROCEDURE AssertEquals(msg:String; expect, act:Longint);
PROCEDURE AssertNil(msg:String; act:Pointer);
{ other asserts ... }
PROCEDURE Fail(msg:String);
{ TestCase }
PROCEDURE SetUp; VIRTUAL;
PROCEDURE TearDown; VIRTUAL;
END;

PROCEDURE TestCase.AssertEquals(msg:String; expect, act:Longint);
VAR ex, ac:String;
BEGIN
IF expect <> act THEN
BEGIN
Str(expect, ex);
Str(act, ac);
Fail(Concat(msg,' expected ',ex,' but was ',ac));
END;
END;

...

PROCEDURE TestCase.Fail(msg:String);
BEGIN
TearDown;
Writeln(' - FAILED');
Writeln(msg);
Halt(1);
END;

PROCEDURE TestCase.SetUp;
BEGIN
END;

PROCEDURE TestCase.TearDown;
BEGIN
END;
Subclasses may overwrite SetUp or TearDown, add test methods and call Asserts. To keep it simple the first failed assertion stops program execution. What's missing is some kind of procedure RunTest that would wrap a particular test method inside calls to SetUp and TearDown. Hmm - function variables might be handy here. In case you are not familiar with them, here is an example:
{$F+} {needs far calls for function variables}
TYPE FuncVar = PROCEDURE;

PROCEDURE FancyMethod(method:FuncVar);
BEGIN
method; { invokes the method }
END;

PROCEDURE SomeMethod;
...

VAR v:FuncVar;
BEGIN
v := SomeMethod;
FancyMethod(v);
END.
Pascal's CalculatorUnfortunately Turbo Pascal does not allow class methods (e.g. TestCase.AssertEquals) to be used as function variables. (At least I couldn't figure.) Obviously self is an implicit parameter of all such methods. Well not obviously, but analysing the generated machine code helps ;-)
SomeMethod; { -> 0E E8 D1 FB }push CS { because of F+ }
call fbe1 { address of SomeMethod in CS }

cls.ClassProc; { -> BF 70 00 1E 57 0E E8 ED FB }
mov DI, #0070 { address of object cls in DS }
push DS
push DI { first parameter is self }
push CS
call fbed { address of ClassProc in CS }
Using this knowledge TestCase.RunTest is implemented a bit dirty using an untyped Pointer argument:
PROCEDURE CallClassPtr(pt:Pointer; VAR cls:TestCase);
VAR s,o:Word;
BEGIN
s := Seg(cls);
o := Ofs(cls);
ASM
mov DI, [o]
mov AX, [s]
push AX
push DI
call [pt.dword]
END;
END;

PROCEDURE TestCase.RunTest(name:String; testMethod:Pointer);
BEGIN
Write('TEST ', name);
SetUp;
CallClassPtr(testMethod, self);
TearDown;
END;
The Prime Factors Kata
Having a simple TPUnit in place, it's time for the kata itself. The seven test methods of PrimeFactorsTest,
PROCEDURE PrimeFactorsTest.Run;
BEGIN
RunTest('TestOne', @PrimeFactorsTest.TestOne );
RunTest('TestTwo', @PrimeFactorsTest.TestTwo );
RunTest('TestThree', @PrimeFactorsTest.TestThree );
RunTest('TestFour', @PrimeFactorsTest.TestFour );
RunTest('TestSix', @PrimeFactorsTest.TestSix );
RunTest('TestEight', @PrimeFactorsTest.TestEight );
RunTest('TestNine', @PrimeFactorsTest.TestNine );
END;
yield
FUNCTION TPrimeFactors.generate(i:Longint):ArrayListPtr;
VAR factors:ArrayListPtr;
candidate:Longint;
BEGIN
factors := new(ArrayListPtr, Init);

FOR candidate := 2 TO i DO
BEGIN
WHILE i MOD candidate = 0 DO
BEGIN
factors^.Add(candidate);
i := i DIV candidate;
END;
END;

generate := factors;
END;
ArrayListPtr is a pointer to a variable sized, user defined list backed by an array of Longints, similar to Java's ArrayList<Integer>. I can't deny I'm a Java guy. Everything I code looks like Java :-) (Probably I would have used a linked list back then instead of a complex object. Something like
TYPE PrimeFactorPtr = ^PrimeFactor;
PrimeFactor = RECORD
value:LongInt;
next:PrimeFactorPtr;
END;
Still the procedure body looks the same and the kata does not change much.)

(Download full source)

13 February 2010

Testing For All One's Worth

End of last year, after a long break, the third part of the 'Code Cop' series has been published in the well known German magazine iX:

Crash DummyTesten, was das Zeug hält (Tägliche Builds mit automatisierten Tests) (iX 1/2010). [... as automated testing is vital for quality assurance, we want to add it to our build. Unit-tests are added easily using JUnit. The same is true for functional testing thanks to a number of already existing tools. By adding testing capabilities to the build, developers are more willing to write tests. In the end the analysis of code coverage achieved by the tests reveals possible weak points ...]

(Download source code of Ant/JUnit/HttpUnit and EMMA integration.)

ReferencesSome other test and code coverage tools mentioned in the article are AgitarOne, dbUnit, Clover, Cobertura, HtmlUnit, JCoverage, Jester, Jtest, JUnitPerf, Selenium, XMLUnit (incomplete list).

(List of all my publications with abstracts.)