Showing posts with label Testing. Show all posts
Showing posts with label Testing. Show all posts

Saturday, March 28, 2020

Clean Unit Testing

It's easy to write "unit test" tests that use JUnit and some mocking library. They may produce code coverage, that keep some stakeholders happy, even though the tests aren't even unit tests and provide questionable value. It can also be very easy to write unit tests that are — in theory — units test but are more complex than the underlying code and hence just add to the total software entropy.

This particular type of software entropy has the unpleasant characteristic of making it even harder for the underlying software to be restructured or to surface new requirements. It is like the test has a negative value.

Doing unit testing properly is a lot harder than people think. In this article, I outline several tips that aim to improve the readability, maintainability and the quality of your unit tests.

Note: for the code snippets, Spock is used. For those who don't know Spock, consider it a very powerful DSL around JUnit which adds some nice features and cuts down on verbosity.

Reason for Failure 


The Unit Test should only fail if there is a problem with the code under test. A unit test for the class DBService should only fails if there is a bug with DBService not if there is a bug with any other class it depends on. Thus, in the unit test for DBService, the only instantiated object should be DBService. Every other object that DBService depends on should be stubbed or mocked.
Otherwise, you are testing code beyond DBService. While you might incorrectly think this is more bang for the buck, it means locating the root cause of problems will take longer. If the test fails, it could be because there is a problem with multiple classes but you don't know which one. Whereas, if it can only fail because the code under test is wrong, then you know exactly where the problem is.
Furthermore, thinking this way will improve the Object Orientated nature of your code. The tests will only test the responsibilities of the Class. If it's responsibilities aren't clear, or it can't do anything without another class, or the class is so trivial the test is pointless, it prompts the question that there something wrong with the class in terms of its responsibilities.
The only exception to not mocking or stubbing a dependent class is if you are using a well-known class from the Java library e.g. String. There is not much point stubbing or mocking that. Or, the dependent class is just a simple immutable POJO where there is not much value to stubbing or mocking it.

Stubbing and Mocking 


The terms mocking and stubbing can often be used interchangeably as if there were the same thing. They are not the same thing. In summary, if your code under test has a dependency on an object for which it never invokes a method on that object which has side effects, that object should be stubbed.
Whereas, if it has a dependency on an object for which it does invoke methods that have side effects then that should be mocked. Why is this important? Because your test should be checking for different things depending on the types of relationships it has with its dependencies.
Let's say your object under test is BusinessDelegate. BusinessDelegate receives requests to edit BusinessEntities. It performs some simple business logic and then invokes methods on a DBFacade (a facade class in front of a Database). So, the code under test looks like this:
public class BusinessDelegate {
     private DBFacade dbFacade;
     // ...

     public void edit(BusinessEntity businessEntity) {
         // Read some attributes on the business entity
         String newValue = businessEntity.getValue();
      
         // Some Business Logic, Data Mapping, and / or Validation

         //...  

         dbFacade.update(index, data)
    }
}

Regarding the BusinessDelegate class, we can see two relationships.


  1. A read-only relationship with BusinessEntity. The BusinessDelegate calls a few getters() on it and never changes its state or never invokes any methods that have side effects. 
  2. A relationship with DBFacade where it asks DBFacade to do something that we assume will have side effects. It is not the responsibility of BusinessDelegate to ensure the update happens, that is DBFacade's job. The responsibility of BusinessDelegate is to ensure the update method is invoked with the correct parameters — only.
So clearly, regarding the unit test for BusinessDelegate, BusinessEntity should be stubbed and DbFacade should be mocked. If we were using the Spock testing framework we could see this very clearly
class BusinessDelegateSpec {
    @Subject
    BusinessDelegate businessDelegate
    def dbFacade

    def setup() {
        dbFacade = Mock(DbFacade)
        businessDelegate =  new BusinessDelegate(dbFacade);
    }

    def "edit(BusinessEntity businessEntity)"() {
        given:
           def businessEntity = Stub(BusinessEntity)
           // ...
        when:
            businessDelegate.edit(businessEntity)
        then:
            1 * dbFacade.update(data)
    }
}

Having a good understanding of stub mock differentiation improves OO quality dramatically. Instead of just thinking about what the object does, the relationships and dependencies between them get much more focus. It is now possible for unit tests to help enforce design principles that would otherwise just get lost.

Stub and Mock in the Right Place 


The curious among you, might be wondering why in the above code sample, dbFacade declared at class level, while businessEntity was declared at method level? Well, the answer is, unit test code is much more readable the more it can mirror the code under test. In the actual BusinessDelegate class, the dependency on dbFacade is at the class level and the dependency on BusinessEntity at the method level.
In the real world when a BusinessDelegate is instantiated a DbFacade dependency will exist, anytime BusinessDelegate is instantiated for a unit test it is ok to have the DbFacade dependency also existing.
Sound reasonable? Hope so. There are two further advantages of doing this:
  • A reduction in code verbosity. Even using Spock, unit tests can become verbose. If you move class-level dependencies out of the unit test, you will reduce test code verbosity. If your class has a dependency on four other classes at the class level that minimum four lines of code out of each test.
  • Consistency. Developers tend to write unit tests their way. Fine if they are the only people reading their code; but this is rarely the case. Therefore, the more consistency we have across the tests the easier they are to maintain. So if you read a test you have never read before and at least see variables being stubbed and mocked in specific places for specific reasons, you will find the unit test code easier to read.

Variable Declaration Order 


This is a follow on from the last point. Declaring the variables in the right place is a great start, the next thing is to do in the same order they appear in the code. So, if we have something like below.
public class BusinessDelegate {

    private BusinessEntityValidator businessEntityValidator;
    private DbFacade dbFacade;
    private ExcepctionHandler exceptionHandler;

    @Inject
    BusinessDelegate(BusinessEntityValidator businessEntityValidator, DbFacade dbFacade, ExcepctionHandler exceptionHandler) {
        // ...
        // ...
    }
    public BusinessEntity read(Request request, Key key) {
         // ... 

    }
    
}

It is much easier to read the test code if they stubs and mocks are defined in the same order as the way the class declares them.
class BusinessDelegateSpec {
    @Subject BusinessDelegate businessDelegate
    //  class level dependencies in the same order
    def businessEntityValidator
    def dbFacade
    def exceptionHandler

    def setup() {
        businessEntityValidator = Stub(BusinessEntityValidator)
        dbFacade = Mock(DbFacade)
        exceptionHandler =  Mock(ExceptionHandler)
        businessDelegate = new BusinessDelegate(businessEntityValidator, dbFacade, exceptionHandler)
    }

    def "read(Request request, Key key)"() {
        given:
            def request = Stub(Request)
            def key = Stub(key)
        when:
            businessDelegate.read(request, key)
        then:
            // ...
    }
}

Variable Naming 


And if you thought the last point was pedantic, you'll be glad to know this one also is. The variable names used to represent the stubs and mocks should be the same names that are used in the actual code. Even better, if you can name the variable the same as the type in the code under test and not lose any business meaning then do that. In the last code sample, the parameter variables are named requestInfo and key and they corresponding stubs have the same names. This is much easier to follow than doing something like this:
//.. 
public void read(Request info, Key someKey) {
  // ...
}


// corresponding test code
def "read(Request request, Key key)"() {
    given:
        def aRequest = Stub(Request)
        def myKey = Stub(key)  // you ill get dizzy soon!
        // ... 

Avoid Over Stubbing 


Too much stubbing (or mocking) usually means something has gone wrong. Let's consider the Law of Demeter. Imagine some telescopic method call...

List queryBusinessEntities(Request request, Params params) {
    // check params are allowed
    Params paramsToUpdate =        queryService.getParamResolver().getParamMapper().getParamComparator().compareParams(params)
    // ...
    // ...
}


It is not enough to stub queryService. Now whatever is returned by resolveAllowableParams() has to be stubbed and that stub has to have mapToBusinessParamsstubbed() which then has to have mapToComparableParams() stubbed. Even with a nice framework like Spock which minimizes verbosity, you will have to four lines of stubbing for what is one line of Java code.
def "queryBusinessEntities()"() {
   given: 
      def params = Stub(Params)
      def paramResolver = Stub(ParamResolver)
      queryService.getParamResolver() = paramResolver
      def paramMapper = Stub(ParamMapper)
      paramResolver.getParamMapper() >> paramMapper
      def paramComparator = Stub (ParamComparator)
      paramMapper.getParamComparator() >> paramComparator
      Params paramsToUpdate = Stub(Params)
      paramComparator.comparaParams(params) >> paramsToUpdate
   when:
       // ...
   then: 
        // ...
}

Yuck! Look at how that one line of Java does to our unit test. It gets even worse if you are not using something like Spock. The solution is to avoid telescopic method calling and try to just use direct dependencies. In this case, just inject theParamComparator directly into our class. Then the code becomes...

List queryBusinessEntities(Request request, Params params) {
    // check params are allowed
    Params paramsToUpdate = paramComparator.compareParams(params)
    // ...
    // ...
}

and the test code becomes

setup() {
    // ...
    // ...
    paramComparator = Stub (ParamComparator)
    businessEntityDelegate = BusinessEntityDelegate(paramComparator) 
}

def "queryBusinessEntities()"() {
   given: 
      def params = Stub(Params)
      Params paramsToUpdate = Stub(Params)
      paramComparator.comparaParams(params) >> paramsToUpdate
   when:
       // ..
   then: 
        // ...
}

All of the sudden people should be thanking you for feeling less dizzy. 

Gherkin Syntax 


Bad unit tests have horrible things like asserts all over the place The top the middle and the bottom. It can very quickly get nauseating trying to figure out which ones are important, which ones are redundant and which ones require which bit of set up etc etc. Schematic things are easier to follow. That is the real advantage of the Gherkin syntax. The scenario is set up in the given: always, the when: is the test scenario and then: is what we expect. Even better using, something like Spock means you have a nice, neat DSL so that the given:, when:, and then: can all be co-located in the one test method.

Narrow When Wide Then 

If a unit test is testing four methods, is it a unit test? Consider the below test:

def "test several methods" {
    given: 
        // ...
    when:
        def name = personService.getname();
        def dateOfBirth = personService.getDateOfBirth();
        def country = personService.getCountry();
    then:
        name == "tony"
        dateOfBirth == "1970-04-04"
        country == "Ireland"
}

First up, if Jenkins tells you this failed, you are going to have to root around and figure out what part of the class is wrong. Because the test doesn't focus on a specific method you don't know immediately which method is failing. Second up, say if it is getName() that is failing, how do you know getDateOfBirth() and getCountry() are working? The test stops on the first failure. So when the test fails, you don't even know if you have one method not working or three methods not working. You can go around telling everyone you have 99% code coverage and one test failing. But — how much was that one test really doing?
Furthermore, what's easier to fix? A small test or a long test? Ideally, a test should check a single interaction with the thing you are testing. Now, this doesn't mean you can only have one asset, but you should have a narrow when and a wide then.
So let's take the narrow when first. Ideally, one line of code only. The one line of code matches the method you are unit testing.

def "getName()" {
    given: 
        // ...
    when:
        def name = personService.getname();
    then:
        name == "tony"
}

def "getDateOfBirth()" {
    given: 
        // ...
    when:
        def dateOfBirth = personService.getDateOfBirth();
    then:
        dateOfBirth == "1970-04-04"
}

def "getCountry()" {
    given: 
        // ...
    when:
        def country = personService.getCountry();
    then:
        country == "Ireland"
}

Now we could have the exact same code coverage, if getName() fails but getCountry() and getDateOfBirth() pass, but there is a problem with getName() and not getCountry() and getDateOfBirth(). Getting the granularity of a test is an entirely different stat to code coverage. It should be ideally one unit test minimum for every non-private method. It is more when you factor in negative tests etc. It is perfectly fine to have multiple asserts in a unit test. For example, suppose we had a method that delegated onto other classes.
Consider a method resyncCache() which in its implementation calls two other methods on a cacheService object, clear() and reload().

def "resyncCache()" {
    given: 
        // ...
    when:
        personService.resyncCache();
    then:
        1 * cacheService.clear()
        1 * cacheService.reload()
}

In this scenario, it would not make sense to have two separate tests. The "when" is the same and if either fails, you know immediately which method you have to look at. Having two separate tests just means twice the effort with little benefit. The subtle thing to get right here is to ensure your assets are in the right order. They should be in the same order as code execution. So, clear() is invoked before reload(). If the test fails at clear(), there is not much point going on to check to reload() anyway as the method is broken. If you don't follow the assertion order tip, and assert on reload() first and that is reported as failing, you won't know if clear() invocation which is supposed to happen first even happened. Thinking this way will make help you become a Test Ninja!
The ordering tip for mocking and stubbing, the same applies to assert. Assert in chronological order. It's pedantic but it will make test code much more maintainable.

Parameterization 

The parameterization is a very powerful capability that can greatly reduce test code verbosity and rapidly increase branch coverage in code paths. The Unit Test Ninja should be always able to spot when to use it!
An obvious indication that a number of tests could be grouped into one test and parameterized is that they have the same when blocks, except for different input parameters.
For example, consider the below.

def "addNumbers(), even numbers"() {
    given:
      // ...
    when:
      def answer = mathService.addNumbers(4, 4);
    then:
      // ...
}

def "addNumbers(), odd numbers"() {
    given:
      // ...
    when:
      def answer = mathService.addNumbers(5, 5);
    then:
      // ...
}

As we can see here the when is the same except the input parameters. This is a no-brainer for parameterization.

@Unroll("number1=#number1, number2=#number2")  // unroll will provide the exact values in test report
def "addNumbers()"(int number1, int number2) {
    given:
      // ...
    when:
      def answer = mathService.addNumbers(number1, number2);
    then:
      // ...
    where:
      number1   | number2   || answer
      4         | 4         || 8
      5         | 5         || 10
}

Immediately we get a 50% reduction in code. We have also made it much easier to add further permutations by just adding another row to the where table. So, while it may seem very obvious that these two tests should have been the one parameterized test, it is only obvious if the maxim of having a narrow when is adhered to. The narrow "when" coding style makes the exact scenario being tested much easier to see. If a wide when is used with lots of things happening it is not and therefore spotting tests to parameterize is harder.
Usually, the only time to not parameterize a test that has the same syntactic where: code block is when the expectations are a completely different structure. Expecting an int is the same structure, expecting an exception in one scenario and an int in another means you have two different structures. In such scenarios, it is better not to parameterize. A proverbial (and infamous) example of this is mixing a positive and negative test.
Suppose our addNumbers() method will throw an exception if it receives a float, that's a negative test and should be kept separate. A then: block should never contain an if statement. It is a sign a test is becoming too flexible and a separate test with no if statements would make more sense.

Summary 

Clean unit testing is very important if you want to have maintainable code, release regularly and enjoy your Software Engineering more.



























Tuesday, February 27, 2018

Testing your code with Spock


Spock is a testing and specification framework for Java and Groovy applications.  Spock is:
  • extremely expressive 
  • facilitates the Given / When / Then syntax for your tests 
  • compatible with most IDEs and CI Servers.
Sounds interesting? Well you can start playing with Spock very quickly by paying a quick visit to the Spock web console.  When you have a little test you like, you can publish it like I did for this little Hello World test.


This Hello World test serves as a gentle introduction to some of the features of Spock.

Firstly, Spock tests are written in Groovy.  That means, some boiler plate code that you have with Java goes away.  There is
  • No need to indicate the class is Public as it is by default.
  • No need to declare firstWord and lastWord as Strings 
  • No need to hurt your little finger with a ; at the end every line
  • No need to explicitly invoke assert, as every line of code in the expect block gets that automatically.  Just make sure the lines in the then: block evaluate to a boolean expression.  If it is true the test passes otherwise it fails.  So in this case, it is just an equality expression which will either be true or false. You can have as many expressions as you want.
So less boiler plate code what next?  Well you know those really long test names you get with JUnit tests, well instead of having to call this test, helloWorldIntroductionToSpockTest() which is difficult to read, you can just use a String with spaces to name the test: Hello World introduction to Spock test. This makes things much more readable.

Thirdly, the Given: When: Then: syntax,  enforces test structure.  No random asserts all the test.  They are in a designated place.   More  complex tests, can use this structure to achieve BDD and ATDD.

Fourthly, if I were to make a small change to the test and change the assertion to also include Tony,  the test will of course fail. But when I get a failure in Spock, I get the full context of the expression that is tested.  I see the value of everything in the expression.  This makes it much quicker to diagnose problems when tests fail.


Not bad for an introduction.  Let's now have a look at more features. 

Mocking and Stubbing

Mocking and Stubbing are much more powerful than what is possible with JUnit (and various add on's). But, it is not only super powerful in Spock, it is also very terse, keeping your test code very neat and easy to read.

Suppose we want to Stub a class called PaymentCalculator in our test, more specifically one of its method, calculate(Product product, Integer count).   In the stubbed version we want to return the count multiplied by 10 irrespective of the value of product.   In Spock we achieve this by:
PaymentCalculator paymentCalculator = Stub(PaymentCalculator)
paymentCalculator.calculate(_, _) >> {p, c -> c * 10}
If you haven't realised how short and neat this is, well then get yourself a coffee.  If you have realised well you can still have a coffer but consider these points:
  1. The underscores in the calculate mean for all values 
  2. On the right hand side, of the second line, we see a Groovy Closure. For now, think of this as an anonymous method with two inputs. p for the product, c for count. We don't have to type them. That's just more boiler plate code gone. 
  3. The closure will always return the count time 10.  We don't need a return statement.  The value of the last expression is always returned. Again, this means less boiler plate code.  When stubbing becomes this easy and neat, it means you can really focus on the test - cool. 

Parameterised Tests

The best way to explain this is by example.
@Unroll
def "Check that the rugby player #player who has Irish status #isIrish plays for Ireland"(String player, Boolean isIrish) {
    given:"An instance of Rugby player validator"
    RugbyPlayerValidator rugbyPlayerValidator = new RugbyPlayerValidator()

    expect:
    rugbyPlayerValidator.isIrish(player)  == isIrish

    where:
    player               ||  isIrish
    "Johny Sexton"       ||  true
    "Stuart Hogg"        ||  false
    "Conor Murray"       ||  true
    "George North"       ||  false
    "Jack Nowell"        ||  true

}
In this parameterised test we see the following:
  1. The test is parameterised. The test signature having parameters tells use this, as do the where block.  
  2. There is one input parameter player and one output parameter - which corresponds to an expected value. 
  3. The test is parameterised five times.  The input parameters are on the left, output on the right. It is, of course, possible to have more of either, in this test we just have one of each. 
  4. The @Unroll annotation will mean that if the test fails, the values of all parameters will be outputted. The message will substitute the details of player into #player and the details of the Irish status substituted into #isIrish. So for example, "Checks that the rugby player Jack Nowell who has Irish status true plays for Ireland"
Again, this makes it much quicker to narrow in on bugs. Is the test wrong or is the code wrong? That becomes a question that can be answered faster.  In this case, of course it is the test that is wrong.

All the benefits of Groovy

What else? Well another major benefit is all the benefits of Groovy.  For example, if you are testing an API that returns JSON or XML, Groovy is brilliant for parsing XML and JSON. Suppose we have an API that returns information about sports players in XML format. The format varies, but only slightly, depending on the sport they play:
Joey Carberry Teddy Thomas
Lionel Messi Cristiano Ronaldo
We want to just invoke this API and then parse out the players irrespective of the sport. We can parse this polymorphically very simply in Groovy.
def rootNode = new XmlSlurper().parseText(xml)
def players = rootNode.'*'.Players.Player*.text()

Some key points:
  1. The power of dynamic typing is immediate. The expression can be dynamically invoked on the rootNode. No verbose, complex XPath expression needed.
  2. The '*', is like a wildcard. That will cover both RugbySummaryCategory and FootballSummaryCategory.
  3. The Player*, means for all Player elements. So no silly verbose for loop needed here 
  4. The text() expression just pulls out the values of the text between the respective Player elements. So why now have a list all players and can simple do:players.size() == 4. Remember, there is no need for the assert. 
Suppose we want to check the players names. Well in this case we don't care about order, so make more sense to convert the list to a Set and then check. Simple.
players as Set == ["Joey Carberry", "Teddy Thomas", "Lionel Messi", Cristiano Ranaldo"] as Set

This will convert both list to a Set which means then order checking is gone and it is just a Set comparison. There's a tonne more Groovy features we can take advantage of. But the beauty is, we don't actually have to. All Java code is also valid in a Groovy class. The same hold trues for Spock. This means there is no steep learner curve for anyone from a Java background. They can code pure Java and then get some Groovy tips from code reviews etc.

Powerful annotations

Spock also has a range of powerful annotations for your tests. Again, we see the power of Groovy here as we can pass a closure to these annotations. For example:
@IgnoreIf({System.getProperty("os.name").contains("windows")})
def "I'll run anywhere except windows"() {...}
Or just make your test fail if they take too long to execute
@Timeout(value = 100, unit=TimeUnit.MILLISECONDS)
def "I better be quick"() {...}
So in summary Spock versus vanilla JUnit has the following advantages:
  1. Test Structure enforced. No more random asserts. Assertions can only be in designated parts of the code. 
  2. Test code is much more readable. 
  3. Much more information on the context of the failed test
  4. Can mock and stub with much less code
  5. Can leverage a pile of Groovy features to make code much less verbose
  6. Very powerful test parameterisation which can be done very neatly
  7. A range of powerful annotations. 
And one of the often forgotten points is that your project doesn't have to be written in Groovy. You can keep it all in Java and leverage the static typing of Java for your production code and use the power and speed of Groovy for your test code.

Until the next time take care of yourselves.

Sunday, July 16, 2017

Outputting the given, when, then, Extending Spock

Spock is a Java testing framework, created in 2008 by Peter Niederwieser a software engineer with GradleWare, which facilitates amongst other things BDD.  Leveraging this example, a story may be defined as:
Story: Returns go to stock

As a store owner
In order to keep track of stock
I want to add items back to stock when they're returned.

Scenario 1: Refunded items should be returned to stock
Given that a customer previously bought a black sweater from me
And I have three black sweaters in stock.
When he returns the black sweater for a refund
Then I should have four black sweaters in stock.

Scenario 2: Replaced items should be returned to stock
Given that a customer previously bought a blue garment from me
And I have two blue garments in stock
And three black garments in stock.
When he returns the blue garment for a replacement in black
Then I should have three blue garments in stock
And three black garments in stock.
Spock makes it possible to map tests very closely to scenario specifications using the same given, when, then format. In Spock we could implement the first scenario as:
class SampleSpec extends Specification{
    def "Scenario 1: Refunded items should be returned to stock"() {
        given: "that a customer previously bought a black sweater from me"
        // ... code 
        and: "I have three black sweaters in stock."
        // ... code
        when: "he returns the black sweater for a refund"
        // ... code
        then: "I should have four black sweaters in stock."
        // ... code
    }
}

What would be nice would be to ensure accurate mapping of test scenario requirements to test scenario implementation. We could get someway down this path if we could output the syntax of the given, when, then from our test.  Spock allows us to add this functionality through its extension framework.

So, let's say our BA is really curious and wants more confidence from the developer that they stuck to the same given, when, then format and their code is in-sync. They want to get this information easily.   Developer could provide this information by first defining this annotation
import java.lang.annotation.*
import org.spockframework.runtime.extension.ExtensionAnnotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ExtensionAnnotation(ReportExtension)
@interface LogScenarioDescription {}
Followed by this implementation:
import org.apache.log4j.Logger
import org.spockframework.runtime.AbstractRunListener
import org.spockframework.runtime.extension.AbstractAnnotationDrivenExtension
import org.spockframework.runtime.model.FeatureInfo
import org.spockframework.runtime.model.SpecInfo


class LogScenarioDescriptionExtension extends AbstractAnnotationDrivenExtension; {
    final static Logger logger = Logger.getLogger("scenarioLog." + ReportExtension.class);

    @Override
    void visitSpecAnnotation(Report annotation, SpecInfo spec) {
        spec.addListener(new AbstractRunListener() {
            @Override
            void afterFeature(FeatureInfo feature) {
                if (System.getEnv("logScenarios")) {
                    logger.info("***SCENARIO TEST:*** " + feature.name)
                    for (block in feature.blocks) {
                        logger.info(block.kind);
                        for (text in block.texts) {
                            logger.info(text)
                        }
                    }
                }
            }
        })
    }
}
This will then be applied to the test
@LogScenarioDescriptionExtension
class SampleSpec extends Specification{
  //...
When the test is executed it gives the following output:
***SCENARIO TEST:*** Scenario 1: Refunded items should be returned to stock
GIVEN
that a customer previously bought a black sweater from me
AND
I have three black sweaters in stock.
WHEN
he returns the black sweater for a refund
THEN
I should have four black sweaters in stock.
output to a specific logfile for scenario logging by using the following log4j:
log4j.rootLogger=INFO, stdout

log4j.logger.scenarioLog.extension.custom=INFO, scenarioLog

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n

log4j.appender.scenarioLog=org.apache.log4j.FileAppender
log4j.appender.scenarioLog.File=logs/scenario.log
log4j.appender.scenarioLog.layout=org.apache.log4j.PatternLayout
log4j.appender.scenarioLog.layout.ConversionPattern=%m%n
and now you have a logfile that your BA, QA can read! This helps foster an Agile culture of collaboration and ATDD where it possible to check that test scenarios implemented with those that were agreed.

Thursday, January 5, 2012

Doing more with less in JUnit 4

JUnit is a popular testing framework for writing unit tests in Java projects. Every software engineer should always try to consider using less code to achieve objectives and the same is true for test code. This post shows one way to write less test code by increasing code re-use using JUnit 4 annotations.
Ok, so let's set the scene. You have a bunch of tests that are very similar but vary only slightly in context. For example, let's say you have three tests which do pretty much the same thing. They all read in data from a file, and count the number of lines in the file. Essentially you want the one test to run three times, but read
a different file and test for a specific amount of lines each time.

This can be achieved in an elegant way in JUnit 4 using the @RunWith and @Parameters annotations. An example is shown below.

W.R.T. to code above:

  1. The RunWith annotation tells JUnit to run with Parameterized runner instead of the default runner.
  2. The @Parameters annotation is defined by the JUnit class org.junit.runners.Parameterized.
    It is used to define the parameters that will be injected into the test.
  3. The data() method is annotated with the parameters annotation. It defines a two dimensional array. The first array is: "players10.txt", 10. These parameters will be used the first time the test is run. "players10.txt" is the file name. 10 is the expected number of rows.
So hopefully this makes sense. Not only is this a way to cut down on test code, it is also a way to provide extra testing of your code. Every time you write a test all you have to do is ask yourself if it makes sense to parameterize your test.
Enjoy...