Wednesday, January 7, 2009
Friday, October 31, 2008
Talk at XPSD Thrusday Nov 6th
we are giving a talk on approval tests at XPSD Thursday Nov 6th at 6pm, here's the teaser...
Approval Based Tests
Write your code, run it, see that it works. This is a familiar process to all programmers. The addition of 1 line of code can now make that a repeatable automated regression test!
Well tested code has been shown, over and over, to improve the quality and maintainability of software. Yet most projects are not well tested. Why is this? Too often programmers feel that testing imposes too high of an overhead on writing code.
In this talk, our goal is to make it easier and faster for you to write unit tests.
We will show how using approvals, in addition to asserts, will great increase not only the ease and speed of writing a test, but the completeness and maintainability of those tests; bridging the gap between people who don't write tests, and test driven developers.
"I feel like I have to write my code twice…" Right now, unit tests impose a difficult step upfront of knowing exactly what you want. Asserting this outcome then becomes cumbersome the more robust & detailed it is. After that, maintaining the test becomes equally cumbersome. Because of this, tests either do not get written, or get discarded, leaving untested code which is fragile, error prone and leads to the nightmare of maintenance so many experience.
After this talk, you should find yourself spending less time writing tests, yet having better tested code, a proven way to increase successfulness of your software.
"After I heard Dan & Llewellyn talk about approval tests, I tried it out… in the first 4 minutes I was testing my code" - C. Monkey
"I find myself writing more code just so I can write more approval tests!" - Script Kiddie
"All my life I'd sought approval from other developers, now I can approve on my own" – Noself E. Steam
"With all the time I saved, I actually learned to talk to women" - Mystery
Thursday, October 30, 2008
Approval Artifact Files
MyClass.myMethod.approved.extention
... and ...
MyClass.myMethod.received.extention
This file resides in the same directory as the source file for MyClass.
Many times this is simply a text file. The output being approved being taken from the toString() method, or a similar printer. Sometimes it is an html file, which is really just a txt file, sometimes it is a Pdf file or Png image file.
Q: Are these files kept in source control?
Yes, the approved files reside in your source control. This has 2 big benefits
1) The test are repeatable on different systems.
2) You can flip back through easy to view output, to pinpoint when and where a bug got introduced.
Q: What configuration is needed?
None.
Q: How can I write to a custom file format?
Simple, all Approvals.approve(object) calls simply construct an approver, and a reporter. The approver is normally a FileApprover, which takes a FileApprovalWriter and an ApprovalNamer.
To do a custom file output simply make your own ApprovalWriter and your own convenience approve() function
Tuesday, October 21, 2008
Downloads on source forge!
Thursday, October 16, 2008
I know exactly what I want!
When creating software, customers don't usually know exactly what they want at the beginning. Agile has checkpoints that allow for quick feedback; while the product is under development, customers can see features as soon as they are completed, giving them an opportunity to accept it or to suggest changes.
Approvals give developers the same opportunity. As a developer, you may not know exactly what you want. The more insight you can get from a result, the more you understand where you want the design to go. That tends to lead us to a more natural flow of coding. You start off with a design in your head, code up an example usage, and implement it. When the result is what you expect, you approve it. With your approved result, you also have a regression test that ensures your expectations don't get violated.
Here's an example test from a bowling game without approvals:
public void TestFourThrows()This is nice; we can see some of the usages for the game object. Now lets take a look at the approval version:
{
game.Add(5);
game.Add(4);
game.Add(7);
game.Add(2);
Assert.AreEqual(18, game.Score);
Assert.AreEqual(9, game.ScoreForFrame(1));
Assert.AreEqual(18, game.ScoreForFrame(2));
Assert.AreEqual(3, game.CurrentFrame);
}
public void TestFourThrows()The approval line doesn’t show us any usages of game like the first example. Glancing at the code we don’t even know what we expect either. When we look at the content of the approval we see:
{
game.Add(5);
game.Add(4);
game.Add(7);
game.Add(2);
Approvals.Approve(game);
}
Frame 2: 18
Current Frame: 3
Total Score: 18
or
| 1 | 2 | 3* | Total |
| 9 | 18 | | 18 |
This output is much more expressive and gives us an understanding of the state of the game object. It allows us to change our internal design without having to change our test code. As we move forward we may find the need to add more information to the output. We make the change, fail the approval, then look it over; if we like the new result we approve it.
Those of us who push a design by writing tests first may have issues with this approach. Instead of creating assertions against primitive types for our expectation just trust the one in your head. While we code our expectations might change. Again, Approvals make it easier for us to change our code without changing the test code. As a discipline we still need to work in small units and design as we go. Our code can also skip those rare artifacts we sometimes need to create for testing. Because we've spent the time up front working out a visual for our code we can easily verify it.
When it comes to pairing, this allows both developers to come up with a common representation of the result they expect. When something fails, instead of double checking if our assertions were correct, we can look at the approval and discuss the expectation as a whole. We spend more time talking about the design instead of how to test it.
There are many ways to test code and they provide different solutions. Some methods push a design, some confirm them, some are used for regression testing. When you write tests, you need to decide if describing the interface is more important or the outcome. Approvals is another tool to help you write better code and get you closer to exactly what you want.
Tuesday, October 14, 2008
Approve is the new Assert
assertEquals(5, person.age());
assertTrue(person.isFemale());
assertEquals("jane", person.getName());
assertPerson(person, "jane doe, female age 5");
Approvals.approve(person.toString());
Name : jane doe
Age : 5
Sex : Female
The more complex the object, the greater the task of writing & maintaining the asserts becomes. While approvals always stay the same one line:
Approvals.approve(yourObject);
Approval Tests (a pictures worth a 1000 tests) [repost]
Component gui = createGui(); Approvals.approve(gui);
Object myObject = createObject(); /*temp*/ Approvals.approve(myObject.toString()); doSomething1(); /*temp*/ Approvals.approve(myObject.toString()); doSomething2(); /*temp*/ Approvals.approve(myObject.toString()); doSomething3(); /*temp*/ Approvals.approve(myObject.toString()); doSomething4(); /*temp*/ Approvals.approve(myObject.toString()); doSomething5(); Approvals.approve(myObject.toString());
Object myObject = createObject(); doSomething1(); doSomething2(); doSomething3(); doSomething4(); doSomething5(); Approvals.approve(myObject.toString());
String allPages = getAllUserProfilePages(); Approvals.approve(allPages);

