Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts

Monday, December 15, 2008

Why I Don't Use "Given, When, Then"

In Introducing BDD, Dan North states that he and Chris Matts were trying to develop a template that, "had to be loose enough that it wouldn’t feel artificial or constraining to analysts but structured enough that we could break the story into its constituent fragments and automate them." This gave birth to Given, When, Then syntax. One example that is given in the article is:

Given the account is in credit
And the card is valid
And the dispenser contains cash
When the customer requests cash
Then ensure the account is debited
And ensure cash is dispensed
And ensure the card is returned

This certainly has structure. But, I personally feel this is still a bit too artificial. Perhaps it is the large amount of content related to the context (account is in credit, the card is valid, the dispenser contains cash). I try to avoid specifying behaviors that have this many moving parts. I would prefer to see a behavior like:

The dispenser when the account is in credit should dispense cash.
The dispenser when the account is in credit should debit the account.
The dispenser when all transactions are complete should ensure the card is returned

I want to read sentences. When possible, I want to read short sentences. Given When Then generates a matrix of sentences to be parsed. GWT also saves some space in the report, but I gladly give that space back to have behavioral sentences that are easier to read quickly.

So, how do I keep the language regular and well-formed? The answer shows up more in the source code of the behvaiors than in the report. So, I might write the following behavior using EasySpec (in Groovy):


@EasySpec(interest='The dispenser')
class Dispenser_happy_path_Test extends GroovyTestCase() {

def account = new Account(balance:1000)
def dispenser = new Dispenser(available:5000)

@Context('when the account is in credit and the dispenser has cash')
public void setUp() {
dispenser.dispense(account, 100)
}

@Behavior
void test_should_debit_the_account() {
assertEquals(900, account.balance)
}

@Behavior
void test_should_dispense_the_requested_cash() {
assertEquals(100, dispenser.totalDespensed)
assertEquals(4900, dispenser.available)
}

@Behavior
void test_should_return_the_card() {
assertTrue(dispenser.lastCardReturned)
}
}

Upon running the EasySpec report, the user will get the following behaviors:


The dispenser when the account is in credit and the dispenser has cash should debit the account

The dispenser when the account is in credit and the dispenser has cash should dispense the requested cash

The dispenser when the account is in credit and the dispenser has cash should return the card


Easy Spec actually generates reports with nice formatting like this.

Perhaps all of this is just personal preference. But, I do find it easy to go back to old specifications and understand what is going on. Language and fluency are important.

You Might Be A Behaviorist...

Are you doing BDD? This is a question I've often heard at recent conferences. As far as I can tell, most people that have looked at BDD concepts are quite sure if they're doing BDD or not. Here are some sign that you might be a Behaviorist:

  1. You talk more about executable specifications and less about "tests."
  2. You write your specifications before you write the production code.
  3. You place high value on natural language in your tests.
  4. You can generate a system-wide report that shows system behaviors in natural language. Bonus points if you do this with every build.
  5. You write your specifications or tests with exactly one context per test class.
Not everyone that is doing these things would classify their projects as using BDD. And, not everyone that says they're using BDD is applying these concepts. But, I think that in the majority of cases you will find a majority of these practices in some form or another.

If I have missed anything, Dear Reader, please let me know.

My English Teacher Would Be Proud -- Proper Language Is Still Important

My high school had one English teacher that was dreaded by all, Mrs. Koch. Mrs. Koch's classes were known to be tough. Most of my friends were accustomed to getting high grades, but this didn't happen too often in Mrs. Koch's classes. Over the course of two semesters, one student got an 'A' in one semester. Mrs. Koch took for granted that we knew the basics that we were supposed to know. For written assignments, she assumed that everything would be spelled correctly and there would be zero grammatical errors. Assignments were graded for content, but grammatical errors caused sever markdowns in one's grade. Language was important.

I am thankful to Mrs. Koch for nurturing a strong sense of grammar in me. Perhaps this is what I have always liked the strict syntax of programming languages. This may also explain why I like Behavior Driven Development so much. Language was critical in Mrs. Koch's class, and language is critical to understanding business software.

BDD brings language into what I believe is its proper place -- the forefront. Language allows developers to understand the business. Language allows the development team to communicate with the project sponsors and domain experts. The more prominent, clear, and accessible our language is, the more readily we understand each other. The more accessible the language is in the code base, the easier it is to understand what we are doing and why we are doing it.

This is why I like BDD so much. When I read through specifications, I can understand what the system does. The more natural the language is, the faster I can stop thinking about syntax and start thinking about the correctness of the system. Natural language also helps to engage the non-developers on the team. While I've watched our project managers look at Java code and guess about what the system is doing, its much easier for us to have a conversation without Java language constructs getting in the way. Likewise, the less we talk about exceptions, try/catch blocks, and if-else statements, the better. Instead, we prefer discussing how the system should and should not behave under certain conditions.

Case in point: Instead of, "The protected area should thrown an exception for unauthenticated users," I would prefer to say, "The protected page should require the user to be logged in." We shouldn't have to acclimate the business types to programmer speak.

Clear language also helps us identity when the design is going astray. One simple word is often a clue to me that a class has too much responsibility. That magic word is, "and." Here's an example:

Lets assume that we're developing a console application that takes in a relatively complex configuration file. The customer has told us that, when the configuration is bad, he wants to be notified in a variety of ways. Sometimes this process will be run manually, and he would like the operator to receive immediate console output for bad configuration. Sometimes, the process is launched automatically and unattended, so he would like configuration problems to be emailed as well. For a final good measure, he has also requested that problems be logged to the logging system we have chosen for the project. We'll assume that the logging and email services live behind a nice interface that is easy to test. We might, then, get a specification that looks like this

The ConfigurationHandler, when some configuration properties are missing and logging is configured and email is configured should log an error for the missing properties and send an email for the error and write an error message to the console.

Assuming that our logging and email systems are properly testable (injected somehow), the actual calls to those services could be a pretty small footprint in the production code. However, this is too much responsibility for the ConfigurationHandler. We see it logging, sending email, printing to the console and killing the process somehow. There are lots of "ands" in the specification indicating that perhaps too much responsibility has been given to the ConfigurationHandler.

If we look at the behaviors shown, they are all about reporting the error. This is when we notice that, perhaps what we need is one more concept called the ErrorService. We can hide all the emailing and logging behind that. So, we break out a new class and a new interface and we end up with the following specifications:

The Configuration Handler, when some configuration properties are missing should report the missing properties to the ErrorService.

The ErrorService should forward errors to the log file, email, and console.


There are still some "and's" there, but the responsibilities are better broken down.

Language is critical to understanding software. BDD helps bring language into more prominence. What does the language of your specifications tell you?

Package Properly: Where Your Tests Live Is Important

About nine months ago, our team decided to start using Behavior Driven Design. Rather than making big changes in the build system to bring in a BDD framework, I put together a BDD reporting framework called EasySpec that allowed us to continue to leverage JUnit. One of our goals in trying BDD was to really push the limits of natural language in testing and determine what the limits were for BDD. We ran into limits with our mocking framework, but Mockito solved those problems for us (more on that in a future post).

One thing that we found was that BDD works pretty well for all levels of testing. Many of the BDD practitioners will only use BDD for higher level integration testing. However, I've found that I really like it for unit-level testing as well. Language is important regardless of where. It is certainly nice to understand system behavior in the large, but as a developer I need to understand behavior in the small as well.

We package our unit-level tests in a test source tree that parallels the production code source tree. So, if I am spec'ing out the com.company.foo.NewFoo, then the production source lives in myProject/src/com/company/foo/NewFoo.java and the first spec will end up in myProject/test/com/company/foo/NewFoo_when_X_Test.java.

One unintended advantage of staying with JUnit and EasySpec was that our new BDD tests landed right next to the old JUnit tests. The subconscious communication that this packaging created was wonderful. It removes the step of questioning where the next test or spec should live. The next spec goes into the parallel package. This also communicates that we are going to be driving the same requirements with BDD that we drove previously using TDD methods. In other words, we aren't just writing larger integration tests with BDD. We are writing as much as possible using BDD because again, langauge is paramount to understanding the system.

How do you package your specs? And, have you pushed the limits to find out how low-level you can drive BDD concepts into your design? I love designing in the small with BDD. My production code is better, and the specification artifacts are wonderful. When supporting code writting six months ago, I find it much easier to understand the system if we have EasySpec specifications rather than JUnit tests -- regardless of the level of abstraction under test.

Friday, March 14, 2008

EasySpec in the works

I have started a new project named EasySpec for doing Behavior Driven Development in Java and Groovy. There is plenty of functionality that I want to add soon, but the core of it is available (as a .jar). The project page on GoogleCode can be found at http://code.google.com/p/easyspec/.

Our team has been using EasySpec for guiding our behavioral specifications for the last three months. I am hooked. If you want specific examples, leave some feedback here. I should be finishing up the current feature development within the next day or so. Then, I will be finishing some examples to be posted by the end of next week.

Monday, January 14, 2008

Mocking Groovy Objects with EasyMock in Java

I mentioned before that I needed to do some unit testing of a class that I was targeting in Groovy with come unit tests in Java. In Java, I am using EasyMock to mock out the collaborators. I am dealing with one collaborator, an interface, that looks like this (Groovy):


interface FileSystem {
...
def uploadFile(inputStream, destinationPath)
...
}

For the purposes of this unit test, I didn't care what got returned, so I setup the expectation like this (Java):

desintationFileSystem.uploadFile(streamForFile1, "someDir\\someOtherDir\\file1.jpg");

Running the test, I was greeted with this message:

java.lang.IllegalStateException: missing behavior definition
for the preceeding method call
uploadFile(EasyMock for class java.io.FileInputStream,
"someDir\someOtherDir\file1.jpg")
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:27)
...

That's when I remembered something fundamental to groovy... the 'def' type means variable return type. For Java, that translates into Object. To make the test run, I either needed to explicitly change the return type on the interface to be void, or simply setup the EasyMock expectation to return a value. Since I didn't want to change the interface, I chose to specify the return value in the expectation.

Sunday, January 13, 2008

How to Cure a Groovy Headache with Java

There was a time during my college years when I was a full-on caffeine addict. I remember once during finals consuming around 10 cans of Dr. Pepper per day. When I decided that I needed to come off the caffeine, I had to use some java (coffee) along the way to avoid the nasty headaches.

Fast forward a few years, and I've once again use some Java to cure a headache. However, today's headache was caused by a mixture of concrete classes and Groovy's seeming inability to mock concrete classes. I wish I knew the Groovy life cycle a bit better to explain exactly why it is that I couldn't mock out java.io.FileInputStream. Suffice to say, Groovy didn't let me substitute in a closure, I didn't want to use mockFor because there was enough else going on. Additionally, Groovy didn't want to cooperate with the EasyMock classextension for reasons I never could quite figure out.

In comes the Java. Since Java and Groovy compile down to the same byte code, testing Groovy with Java is pretty easy. The final solution that I came up with was writing the implementation in Groovy like I wanted to, and writing the test in Java. I simply used org.easymock.classextension.EasyMock to do the mocking, and away we went. This was a nice proof of Java and Groovy living right next to each other and working together. One of the nice things about having the ability to do the test in Java was proving that, indeed, I had all of the project dependencies that I needed and Groovy just did not like mocking out the class.

Watch here soon, and I am going to post a cool little tool that I am working on for spiking the project structure for a setup like this. It's much more stripped down from what Grails will give you. But, if your looking for directory structure and a simple build.gant, then this may be something to look at.

Now, where's my decaf coffee?

Tuesday, October 30, 2007

Programmers Anonymous: Confessions of a Terrible Software Developer

Marc has posted his "Confessions of a Terrible Programmer." The overriding tone of the post can be summed up in the following pseudo-Zen quotes:


You will never become a Great Programmer until you acknowledge that you will always be a Terrible Programmer.

and,

You will remain a Great Programmer for only as long as you acknowledge that you are still a Terrible Programmer.

Marc does a very good job of stating how he overcomes his "terribleness" to provide working software. According to Marc, his solutions are doing a good job of hiding the fact that he is a terrible developer. However, I believe that agile practices present different solutions to these problems. In broad terms, Marc favors failing fast where I favor multiple levels of testing, Test-Driven Design, and the fast feedback loops provided by good test coverage coupled with Continuous Integration.

To address more specifics, I have provided a summary of Marc's solutions along with where I think agile solves these in a different way.

  1. Marc says he favors strong typing to prevent problems. Having done most of my work in static languages (Java, C#), and some in dynamic language (Groovy), at this point I prefer solid unit test coverage (100% with excuses). Test-first design helps with this too. Once I have good test coverage, those tests are unearthing the same problems that the compiler would. With the dynamic languages, I find the same errors a bit later, but I get the benefit of code that I find to be much easier to read.

  2. Marc favors programming assertions. Marc is a paranoid programmer. He will assert that something is not null even when he controls both sides of the interface - just in case he might change something later. I personally find that assertions and paranoid programming in general fall under the related headings of YAGNI and nosiy code. Instead, I prefer solid unit testing and a tester that knows how to unearth the edge cases. Write unit tests that assert that the service in question does not return null to box in the behavior.

  3. Marc says he will, "ruthlessly try to break [his] own code." It appears that Marc is trying to accomplish through developer testing what should be done by an actual tester. While I agree that developers should be generating tests that give great code coverage, it is a waste of time to make them switch hats and become a tester for their own code. Hire a tester. They think differently from developers. Their concerns are different.

  4. Marc favors code reviews. I favor pair programming. Both provide feedback, but I want my feedback while I'm "in the zone." I want my feedback immediately. I don't want you to sit back and wait for me to find my own bugs. If you see something, tell me. Tell me as soon as it looks like I've finished typing or as soon as it looks like I'm looking for the bug. This way, I can fix the problem without having to make the context switch to come back to it later. Plus, the quality of the review is better since the other developer should be equally engaged in the generation of the code while it is being generated.


To be honest, our team is not able to follow all of these guidelines at the moment. Our biggest problem is not having a dedicated software tester embedded with the team. We ARE having to generate the types of tests that a dedicated tester should be doing. And, we are missing some things that a tester would catch much earlier in the development process. I feel that this missing component of our team IS hurting our velocity.

Am I a terrible programmer? Yes. If you find me stating otherwise, please redirect me to some of my own code - something that I wrote yesterday should do just fine.

What are you doing to hide the fact that you're a terrible developer? I would love to hear.

Wednesday, October 3, 2007

Don't Use Mocks...

...when you aren't really interested in testing the interactions. This is related to my previous post regarding mocks and stubs. If leaving off the verification of mocks wouldn't change the nature of what you are testing, then you aren't writing an interaction-based test. Therefore, the mock dependency probably creates more noise than simply using a simple stub. If your dependency is not behind an interface, you can in most cases still create a stub using subclass and override.

While writing:


Dependency dependency = createMock(Dependency.class);
expect((Foo)dependency.bar(anyObject())).andReturn(somethingValid);
ThingToTest target = new ThingToTest(dependency);


isn't too bad. It still causes more noise than:


ThingToTest target = new ThingToTest(new DependencyStub());


Most of the time, I see that stub and grok the fact that in the context of this test, I really don't care what the Class under test does with that dependency.

Saturday, September 29, 2007

Write better tests using a combination of mocks and stubs.

I love using EasyMock. It's just plain, well, easy to use most of the time. Most of the time, it doesn't get in my way. However, there are certain times when I will avoid using a mock object in a test. This is best show by example.

As background, remember that mocks are not stubs and stubs are not mocks. You can use a mocking framework (like easymock) to create stubs, and you can even create mocks by hand (with a good deal of pain). Roy Osherove has done a great job of describing the differences between mocks and stubs. You should check out Roy's explanation. This is a different explanation from what I've seen before. If you want a good, detailed description of the differences, Martin Fowler has provided an in-depth comparison between the two including code samples. You should take a look at Fowler's explanation to understand the terminology.

I won't rehash the explanations. What I will say is that I've found value in doing both interaction-based testing (with mocks) and state-based testing (with stubs). When your classes are well decomposed and decoupled, mock testing makes more sense in most cases. However, when I'm interested in how a particular piece of code affects state on objects that pass through it, I will use a stub.

Here's the promised example. Supposed a I have a class, we'll call Processor that interacts with a dependency that sits behind and interface called EmailService. I'm interested in testing that Processor.emailManagers("we have a problem") can create an instance of Email with the correct properties set and hand that off to the EmailService. Looking at the test first, we have:

@Test
public void myTest() {
EmailServiceStub serviceStub = new EmailServiceStub();
Processor processor = new Processor(serviceStub);
processor.emailManagers("This should be working");

email = serviceStub.getLastSentEmail();
assertNotNull(email);
assertEquals("This should be working", email.getMessage());
assertEquals("managers@FooInc.com", email.getTo());
assertEquals("An Automated Message from 'The System'", email.getSubject());
assertEquals("TheSystem@FooInc.com", email.getFrom());
}

Obviously, we'll need something to stand in the place of the EmailService so that we don't actually send an email in the course of running this unit test. The stand-in for this test is done by a stub like this:

public class EmailServiceStub implements EmailService {
Email lastSentEmail = null;

public void send(Email email) {
this.lastSentEmail = email;
}

public Email getLastSentEmail() { return this.lastSentEmail; }
}


The actual implementation code for Processor then might look like this:

public class Processor {
EmailService emailService;
public Processor (EmailService emailService) { this.emailService = emailService}

public emailManagers(String message) {
Email email = new Email();
email.setBody(message);
email.setSubject("An Automated Message from 'The System'");
email.setTo("managers@FooInc.com");
email.setFrom("TheSystem@FooInc.com");

emailService.send(email);
}
}



To be fair, this kind of testing is possible with EasyMock as well. You CAN check the properties of the object that are passed to send() using EasyMock. However, I find it incredibly painful to do so. What's worse, it makes the test convoluted to read. EasyMock would have you define your own implementation of IArgumentMatcher as indicated here. (search for "Defining own Argument Matchers"). Blech! We've done this before, and it seems to make the tests much more difficult to grok when I come back to them.

There are plenty of good examples of when you would want to use mocks over stubs. The Fowler post linked to at the top is a good start. I still use mocks for most of my testing, but in this instance, it's easier to use a stub than battle EasyMock.

Monday, August 13, 2007

Throw Away Code Must Be Thrown Away

From time to time, it’s advantageous to take off my TDD hat a fling a small bit of code. I’ve found this is the quickest way to gain a bit of confidence in working with libraries that I haven’t touched before. This allows me to be sure that I know how to interface with the functionality that I need. After a quick proof-of-concept, I’ll know what parameters and classes are needed to get what I want.

My own personal problem with this has been developing the discipline to remove the code from the system once I’ve figured out what I’m after. Why do I think I need to discipline myself to do this? Simply put, my worst code is always the code that wasn’t written “test-first.” The spikes that I pull over into production code often cause problems when trying to get them under test coverage.

Conversely, I’ve found that following Test Driven Development yields code that is easier to test and frankly, better designed. TDD prevents a great deal of speculative development and over design. Therefore, it’s much better to step back from the initial spike and start over by writing tests.

I have found it much easier to prevent the spikes from getting attached to the project by putting them in a completely separate class. Name it “class ThrowAway” to help yourself remember.

Bottom line: Throw-away code must be thrown away.