Sunday, May 1, 2016

Unit Testing Spring Applications

Abstract: there are at least four ways to handle dependency injection for unit testing a Spring application: configuration by Spring XML configuration file, DIY injection, Spring's Java API, and Spring's injection via Reflection utility. The later three are suitable for unit tests. At the end are benchmarks for each strategy and a discussion on using Mockito with Spring.

You're a hot shot Java developer so of course you're doing the XP practice of TDD. You're working with Spring, then SHAZAM! You need to inject a mock dependency and are wondering how to do it. To make matters worse, you notice every time you add a new test class with @RunWith(SpringJunitTestRunner), those tests take two orders of magnitude longer to execute. (The other
tests run in milliseconds, SpringJunitTestRunner tests take hundreds of milliseconds.

What's happening?

Spring isn't a lightweight framework. It does a lot of work in the background, some of which includes looking around for spring configuration XML files on the file system.
Although you wanted to write fast feedback *unit* tests, now you're dependent on file system resources! Here is a simple example to illustrate the strategies to unit testing a Spring application.
MainApp.java:
package foo;

import org.springframework.beans.factory.annotation.Autowired;

@Component()
public class MainApp {
 // NullPointerException occurs if no injection
    @Autowired()
    private MessageBean helloWorld;
    // A command line app needs to setup ApplicationContext.
    public static void main(String[] args) { 
        ClassPathXmlApplicationContext spring = new ClassPathXmlApplicationContext("beans.xml");
        springInjectAndDoWork(spring);
        spring.close();
    }
    // separated the concern of deciding what kind of ApplicationContext from the work.
    public static void springInjectAndDoWork(ApplicationContext spring) {
        MainApp app = spring.getBean(MainApp.class);
        MessageBean message = (MessageBean) spring.getBean("helloWorld");
        app.callGreeter();
    }

    public void callGreeter() {
        helloWorld.getMessage();
    }
}
MessageBean.java:
package foo;
import org.springframework.stereotype.Component;

@Component
public class MessageBean {
   public void getMessage(){
      System.out.println("My Message  ");
   }
}
beans.xml (tap to read):
And unfortunately, this often done trap of building a charlatan unit test is:
package foo;
import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("beansTest.xml") 
public class SpringTestRunnerAndXMLFileTest {
    @Test
    public void construct_callToMainThrowsNoException() {
        MainApp main = new MainApp();
        main.main(null);
    }
}
This will allow you to build test automation but is this strategy appropriate for *unit* test automation?
Using the SpringJUnit4ClassRunner creates a Spring ApplicationContext and enables some hooks such as specifying the spring configuration file to use.
Problem 1: slow
Tests that require filesystem access can never be a unit test. Tests like the above will load the spring configuration .xml file and this will turn a test that takes tens of milliseconds into something that takes hundreds.
Problem 2: poor isolation
Each @Test method often needs to insert different fake data via Spring’s dependency injection. Having a different config file for each situation means moving valuable information from a single source (the test class or test method) into a separate file at the expense of making it harder to maintain.  Also, these config files tend to be used like shotguns, loaded with a bunch of beans that aren't specific to supporting any specific test's injection. This makes maintaining the test harder. Most developers create a single XML file to be used for a lot of test classes becoming a "global" shared by all the project's tests. When the XML file becomes flawed, then many unit tests are affected because the file becomes a dumping ground for injection for many tests rather than a single test.  Like anything "global" the file can't scale to many tests and becomes an "untouchable" that no one wants to fiddle with because no one can predict the impact. This situation can be improved by creating an XML file customized for each test so the XML file becomes documentation for each specific test class.

Alternatives

Here are some strategies that scale to supporting hundreds to thousands of tests and give fast feedback.

DIY Injection

When unit testing, dump Spring framework and inject the beans yourself. When your application runs in production, it still uses Spring.
Drawbacks: 
  • adding to the class under test's API for injection via: constructor injection or setters. If you've got a lot of collaborators, the API reflects the dependencies (for good or bad).
Positives: 
  • Fast. In fact, so fast my laptop reports 0ms.
  • Doing say Constructor Injection, leaves a nice clear design artifact for future test creators to use because it documents in one location all the dependencies.
  • Test isolation is maintained as each test is injecting only what it needs. And if you do this well, your test documents what collaborators it depends on for the test.
  • Configuration is located in the test class making maintainability easier.
package foo;
import org.junit.Test;
public class DIYInjectionTest { 
    @Test
    public void construct_callToMainThrowsNoException() {
        MainApp main = new MainApp(new MessageBean());  // using DIY constructor injection
        main.callGreeter();
    }
}
package foo;
import org.springframework.beans.factory.annotation.Autowired;
@Component()
public class MainApp {
    @Autowired()
    private MessageBean helloWorld;

    MainApp(MessageBean messageSender) { helloWorld = messageSender;    } // added for DIY injection test

    // A command line app needs to setup ApplicationContext.
    public static void main(String[] args) {  // this main commits you to XML, so put very little code in here or make your caller give you an ApplicationContext.
        ClassPathXmlApplicationContext spring = new ClassPathXmlApplicationContext("beans.xml");
        springInjectAndDoWork(spring);
        spring.close();
    }

    // separated the concern of deciding what kind of ApplicationContext from the rest of the work.
    public static void springInjectAndDoWork(ApplicationContext spring) {
        MainApp app = spring.getBean(MainApp.class);
        MessageBean message = (MessageBean) spring.getBean("helloWorld");
        app.callGreeter();
    }

    public void callGreeter() {
       helloWorld.getMessage();
    }
}

Spring's Configuration Java API

Use Spring’s java classes to configure how to perform the Spring injection by creating a class that models what's in the configuration XML file using annotations such as @Configuration, @Bean, ... etc.
Drawbacks:
  • If you've a ton of injection to do for the unit under test, you'll feel the pain that was hidden within the XML configuration file by needing to express the configuration again as Java code. This pain can be made easier by pushing that code into a super class if a lot of test classes require it
Positives:
  • Fast. 
  • Keeps injection happening via Spring so no class's interface needs to be changed.
  • Test isolation is maintained.
  • Configuration is collocated with its test class (assuming you're using a static inner class like the below example)
package foo;
import org.junit.Before;
public class SpringConfigurationAPITest {
    // The below inner class strategy doesn't work unless the class is static.
    @Configuration
    static public class ContextConfigurationAsInnerClass {
        @Bean
        public MessageBean helloWorld()    {return new MessageBean();}
        @Bean
        public MainApp mainApp() {return new MainApp();}
    }

   
    @Test
    public void construct_callToMainThrowsNoException() {
        MainApp main = new MainApp();
        ApplicationContext spring = new AnnotationConfigApplicationContext(ContextConfigurationAsInnerClass.class);
       
        main.springInjectAndDoWork(spring);  // using Spring injection but without an XML file
    }
}

SpringTestUtil

Spring provides a simple API that lets you inject the collaborators your test needs and does it with less effort than using its Java Configuration API. Simply use ReflectionTestUtils.setField(...) to inject the collaborators. It will do this regardless if the field you're injecting to is private.

Drawbacks:
  • if you've got a lot of injection to do, you need to make a lot of calls to setField.
Positives:
  • fast
  • test isolation is maintained
  • no changes to the class under test's API.
  • it doesn't require Spring framework to be active (no need for an ApplicationContext).
  • this api is simpler than configuring Spring using its Java Configuration API.
  • Configuration is collocated with its test class. This strategy documents the dependencies that are necessary to unit test the class under test, keeping maintainability easy and what to do when creating more new tests
package foo;
import org.junit.Before;
public class SpringReflectionInjectionTest {
    private MainApp main;
   
    @Before
    public void injections()
    {
        main = new MainApp();
        ReflectionTestUtils.setField(main, "helloWorld", new MessageBean());
    }
   
    @Test
    public void mainThrowsNoException() {       
        main.callGreeter();
    }
}

Benchmarks

Here are the benchmarks for the four strategies.
Run 1:
Run 2:
Notice the test that depends on the configuration file has a large variance in run time. I've seen it take as long as 700ms on my SSD laptop. Remember that this is only one test. Real applications that are under development for twelve months (five developers) typically need about three thousand tests and easily get them to execute in 3 minutes, or 60 milliseconds per test method. If your tests require configuration files to work then you're looking at 9 to double digit minutes. A lot of human factors on feedback will work against you because few people are going to sit at their workstation to wait for those tests. When the tests take a long time to give feedback, people are already checking email or taking a break, losing context of what they did. The wait state is too long.
And if you keep this application around for the industry average of 10 years, it's not uncommon you'll have ten thousand tests. Beyond the cost of waiting for feedback, it's harder to maintain tests that depend on external XML files. The test triangle refers to the geometric concept that unit tests should be most numerous just as the area of the unit test section is much greater than the UI area of the triangle.
Now you've got three strategies for making fast feedback unit tests for a Spring application (bottom of the triangle) and XML files for slower feedback system tests (the middle tier of the triangle). Like a golfer who selects the "best club for the situation" you want to use the best tool for the job.

Spring and Mockito

Many people on the Java stack are using Mockito for mocking their objects. Not only can Mockito be used to mock objects, it can inject those objects similar to Spring. Out of the many ways to inject Mockito mocked beans, here are the most promising ones: use SpringTestUtil.setField(...), use Spring to inject mocks, or use Mockito injection. 

SpringTestUtil.setField(...)

One common configuration is to use Mockito to build the mocks then use SpringTestUtil.setField(...) for injection. Just change the example code for SpringTestUtil.setField(...) to:
 @Before
    public void injections()
    {
        main = new MainApp();
        ReflectionTestUtils.setField(main, "helloWorld", Mockito.mock(MessageBean.class));
    }

Configure Spring to inject Mockito Mocks

Using Sprig's Configuration Java API to return Mockito mocks:
package foo;
import org.junit.Before;
public class MockitoMockInjectionViaSpringConfigurationAPITest {
    static private MessageBean messageBeanMock;
    // I'd rather not use static, but Inner class @Configuration doesn't work unless the class is static.
    @Configuration
    static public class ContextConfigurationAsInnerClass {  
        @Bean
        public MessageBean helloWorld()    {return messageBeanMock; }
//alternatively, put Mockito.mock(...) here
      
        @Bean
        public MainApp mainApp() {return new MainApp();}
    }
   
    @Before
    public void initStaticsToMaintainTestIsolation(){messageBeanMock = Mockito.mock(MessageBean.class);    }
   
    @Test
    public void construct_callToMainThrowsNoException() {
        MainApp main = new MainApp();
        ApplicationContext spring = new AnnotationConfigApplicationContext(ContextConfigurationAsInnerClass.class);
      
        main.springInjectAndDoWork(spring);  // using Spring injection but without an XML file
        Mockito.verify(messageBeanMock).getMessage();
    }
}

Mixing Mockito injection with Spring injection

Mixing Mockito mock injection with Spring mock injection is tricky. Mockito does injection upon calling MocktioAnnotations.initMocks(...) or when JUnit sets up the test class via @RunWith(MockitoJUnitRunner). Spring does it's injection when you call ApplicationContext.getBean(...) or when JUnit tests up the test class via @RunWith(SpringJUnit4ClassRunner). (Hopefully you won't use SpringJUnit4ClassRunner as you'll not have a unit test when you're finished.) You'll need to understand what's happening and when so you don't have your mockito injected objects later overwritten by Spring's injection. Although getting this working is doable I try to avoid un-necessary complications so I'll move on to using Mocktio only injection.

Mockito injection

Mockito injection is configured with @Mock and @InjectMocks. Mark beans, etc, to be injected with @Mock.  Mark the class to inject the @Mock(s) into with @InjectMocks. Injection is triggered by using @RunWith(MockitoJUnitRunner) on the Test class or explictly calling MockitoAnnotations.initMocks(...).
package foo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MockitoRunWithInjectionTest {
    @Mock
    private MessageBean messageBeanMock;
    @InjectMocks
    private MainApp main;


    @Test
    public void construct_callToMainThrowsNoException() {       
        main.callGreeter();
        Mockito.verify(messageBeanMock).getMessage();
    }
}
Or by using initMocks(...):
package foo;
import org.junit.Before;
public class MockitoInjectionViaExplicitCallTest {
    @Mock
    private MessageBean messageBeanMock;
    @InjectMocks
    private MainApp main;

   
    @Before
    public void doInjections()    {MockitoAnnotations.initMocks(this);}

    @Test
    public void construct_callToMainThrowsNoException() {       
        main.callGreeter();
        Mockito.verify(messageBeanMock).getMessage();
    }
}
Mockito uses Reflection and runtime bytecode generation to mock objects. Because Mockito is slower than simply using POJOs (plain old java objects) it's better to use your product's objects if they are suitable for the task. Since Mockito doesn't use files for configuration, its impact isn't the two orders of magnitude of using Spring and XML configuration files.
For some great background on WHY writing FAST and Furious micro tests is so important, listen to the short, to the point, and entertaining Testing Pyramid series (episodes 1 through 8) on the Agile Thoughts podcast.
Episodes 1 through 8

References

How Spring Inversion of Control works

http://docs.spring.io/autorepo/docs/spring/3.2.x/spring-framework-reference/html/beans.html
Using Spring 4 for Dependency Injection and why you'd want a dependency injection framework.
https://www.youtube.com/watch?v=6F3Cv1a7G0w

Using Spring in a standalone app

http://stackoverflow.com/questions/3659720/using-spring-3-autowire-in-a-standalone-java-application?lq=1

Spring's JUnitTestRunner

http://docs.spring.io/autorepo/docs/spring-framework/3.2.6.RELEASE/javadoc-api/org/springframework/test/context/junit4/SpringJUnit4ClassRunner.html

http://lstierneyltd.com/blog/development/examples/unit-testing-spring-apps-with-runwithspringjunit4classrunner-class/

SpringTestUtil

http://mrhaki.blogspot.com/2010/09/private-spring-dependency-injections.html
http://stackoverflow.com/questions/6840939/what-is-the-best-way-to-inject-mocked-spring-autowired-dependencies-from-a-unit

Spring Configuration Java API

http://www.nurkiewicz.com/2011/01/spring-framework-without-xml-at-all.html
Application Contexts to use with the above:
http://docs.spring.io/autorepo/docs/spring/4.1.1.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html

Common gotcha's:

Most of the examples on the internet have people making "top level" java classes annotated with @Configuration. This is not a good model for unit tests where the unit test should (as much as is practical) be a simple record for setting up a unit test. It's really better to use an inner class. If you see the below exception regarding your inner @Configuration class, declare it "static" as I did in the code example.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springConfigurationAPITest.ContextConfigurationAsInnerClass': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [foo.SpringConfigurationAPITest$ContextConfigurationAsInnerClass$$EnhancerBySpringCGLIB$$a473a0f4]: No default constructor found; nested exception is java.lang.NoSuchMethodException: foo.SpringConfigurationAPITest$ContextConfigurationAsInnerClass$$EnhancerBySpringCGLIB$$a473a0f4.

About static inner classes:

http://www.geeksforgeeks.org/static-class-in-java/

Testing Triangle (or incorrectly referred to as Testing Pyramid :-)

Friday, October 16, 2015

Test Driven Development Environment for Javascript

Episodes 1-8

Even though JS frequents the GUI slice of an architecture diagram, there is ample functionality that can be unit tested. (For an overview of the testing pyramid, Agile Thoughts podcast has a nice overview on this topic.) The Javascript environment has a a rich history of unit testing tools.  JSUnit is the earliest that I know and was part of the initial wave of xUnit test frameworks in early 2000.  Due to the explosion of xJS frameworks in the last three years, it's time to update knowledge of what tools to use for doing TDD in Javascript.

The tool chains I evaluated were: NodeJS + Karma + Jasmine versus NodeJS + Karma + Mocha + Chai + Sinon.

Here is what they do:
NodeJS is a javascript runtime environment which will run our test tools.
Karma enables pushing our tests into different browsers and automated test launching.
Jasmine versus Mocha + Chai are two choices for test libraries for organizing our tests and give us ways to build assertions.
Jasmin versus Sinon are choices for Mocking

Take a look at the picture below and you'll see the same unit test expressed in three different was.
Jasmine
The above is a nice incremental improvement on typical xUnit with the "toBe."

Mocha and using Chai's "expect"

Using Chai's expect is a bit better than Jasmine's as it allows building of "chains of purpose."

Mocha and using Chai "Should"
I wanted to use Jasmine since it included a lot of functionality as opposed to installing Mocha + Chai + Sinon.  But Chai's "should" is really superior as it prominently shows what is being tested (translate in this case) and gets to the point about what's expected.  Notice how you're less likely to develop "parenthesis blindness."  Here is a good overview of mocha, chai, sinon.  Let's talk about how to put these tools pulled together into an environment.

Install and setup NodeJS, Mocha, Chai, Sinon

1) https://nodejs.org/en/

Install a javascript runtime and package manager.  We'll use NodeJs's package manager to install the remaining tools.  NodeJs's runtime will be used to operate our tools, which are also written in javascript, on our workstation.  Make a work directory to install your javascript test tools.  From this location, you'll configure the test tools to find your source code.

2) Karma and Friends

I opted for Karma to Javascript code in assortment of browsers in order to execute the tests in the browser environments.  Karma will do all this automatically by running a server to controll those browser environments in NodeJs.

Install the Karma cross browser execution framework:
npm install karma --save-dev
npm -g install karma-cli
"-g" is used to do a "global" install, meaning get class paths setup so you can conveniently execute it.

The steps at http://attackofzach.com/setting-up-a-project-using-karma-with-mocha-and-chai/ are pretty close but miss on the dependencies as they've changed since authored, and "npm init" is unnecessary.  So here is what to do:
npm install X --save-dev, where X =>{mocha, karma-mocha, chai, karma-chai, sinon, karma-sinon, karma-chrome-launcher}
Said another way:
npm install mocha  --save-dev
npm install karma-mocha  --save-dev
npm install chai --save-dev 
npm install karma-chai --save-dev
npm install sinon --save-dev   
npm install karma-sinon --save-dev
npm install karma-chrome-launcher --save-dev

(If after doing a "npm install... "and there's a warning about not installing dependencies, respond by installing those dependencies explicitly as ordered to by the computer.)

3) Initialize karma

karma init
"Karma init" will interrogate about the below to generate a boilerplate karma.conf.js.  You'll want to tell it the following:

  • select mocha test framework
  • Add Require.js which we'll use for loading dependencies.
  • Select what browser(s) you want to test against.
  • For location of source files, I used the below. After you're up and running and have written a few tests, you'll want to change the source code settings to point at your code under source control:
    • js/*.js
    • test/*.js
    • lib/*.js 
    • Exclude js/main.js if you have a main.js so that your application under tests doesn't get control of the javascript boot loader.  You want your tests to be loaded and executed rather than your application, right?
  • Accept the defaults for the rest.

4) example karma.conf.js

My file looks like the below.  Note especially the frameworks setting as you'll need to add chai.  If you messed up during the init interrogation, then you can correct it by hand.
Check karma.conf.js to see that you've got the correct file filtering setup.  As of today, the Windows install of Karma does the wrong thing and filters out all your tests.  You want included:true.
 // list of files / patterns to load in the browser
    files: [
      {pattern: 'test/*.js', included: true},
      {pattern: 'lib/*.js', included: true},
      {pattern: 'js/*.js', included: true}
    ],
Here is my entire config file on Windows.
module.exports = function(config) {
  config.set({
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',
    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'sinon-chai'],
    // list of files / patterns to load in the browser
    files: [
      {pattern: 'test/*.js', included: true},
      {pattern: 'lib/*.js', included: true},
      {pattern: 'js/*.js', included: true}
    ],
    // list of files to exclude
    exclude: [
      'js/main.js'
    ],
    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },
    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],
    // web server port
    port: 9876,
    // enable / disable colors in the output (reporters and logs)
    colors: true,
    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,
    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],
    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  })
}

Test the environment

Type: $karma start
Hopefully you see this:
If you read the messages carefully, you'll see that it didn't find any tests to executed.

If "karma start" fails, then the karma.conf.js likely has an error.  Read the message and see if you can figure out what it's asking for, then use "npm install" to install what's missing or fix the problem in karma.conf.js.  If you get no error, it just runs the karma process.

If Karma is running, you'll see a browser window launched. This is what Karmar does: it uses a NodJS server client and server (one that can access you tests in the configured test directory, and one in the browser(s) in which you want to execute the unit test.


Lets write a test:

describe("This test suite will fail", function() {
   it('should fail', function() {
         expect(false).to.be.false;
    expect(true).to.not.be.true;
   });
});
As soon as the test is saved, the part of Karma that is watching your test directory files for changes, will grab that test and ship it to the browser(s) it's controlling.  After running the test on the browser(s), it returns a report to the Karma controlling running in your DOS prompt and will write out the results.  In the DOS prompt where you launched Karma, you should see something like this:

What's Karma, What's Mocha, What's Chai?

Karma runs in Nod.js and looks for and executes test ".js" files.  It loads the .js file and executes any "describe(...)."  Mocha, the "test runner" handles reporting results.  In the test above, Mocha is called via the "it(...)."  Chai is the library for investigating test results using "expect(...)" among many other library calls.

Mocking

Karma-chai-Sinon plugin is a good way to get everything you needed installed in fewer step. I'll update the above with this improvement. Then I'll put a nice mocking tutorial here. 

Tips

Karma tips: http://www.methodsandtools.com/tools/karma.php

Trouble shooting

When karma executes against a changed test, it returns Executed 0 of 0 ERROR

This happen because my karma.conf.js had, in the FILES section, had "exclude=true." This problem is also documented at: https://github.com/karma-runner/karma/issues/713

After "karma start" returns: Delaying execution, these browsers are not ready:

Recently, this happened when I tried to use RequireJS as a framework in my karma.conf.  When I removed this, it worked.  I don't need RequireJS.  Lots of people do.  I'm sure there is a way to get this to work.  Please comment if you know how to fix that problem.

Thursday, April 9, 2015

Know thy Most Productive Mode (part 2 of Having Great Standups)

When working with new Scrum teams, team members often don't recognize what is impeding them because even though something is obvious to me, to them it's business as usual.

Working with these new teams, I've stumbled upon a way to structure their thinking around this retrospection: Identifying the Most Productive Mode. Once the team knows what their most productive mode is, they can see what is impeding their ability to reach that state. Once they "see it" then they can do something about it such as bringing it up at standup.


MOST PRODUCTIVE MODE

Teams under stress will feel that cutting out some of their new development practices will somehow make them go faster. This is a natural reaction to fear--going back to the old way. This is why it's so important for each team member to intellectualize (know) why they are doing the practices and how *not* doing them will slow them down.

It's better to deliver as much code as you can with your new good practices and communicate what is keeping you from reaching your most productive mode:

Characteristics of productivity
Focus-- focus on one task at a time and getting the artifacts finished and checked in before dealing with distractions (email, phone, meetings, lunch break). Do this work with another (pair programming) who can bring immediate feedback, mentorship, and different perspective

Quick Feedback-- create feedback loops so you know ASAP that something is right or wrong:
writing tests and code in baby-steps (Test Driven Development);
executing the unit tests at least once every fifteen minutes and recognizing you've bitten off too much to do in one step when you can't (a coverage report is a medium-slow feedback mechanism, but will be a constant one once we get it fixed so it gives you feedback every time you run the tests in JUnit); and
getting feedback on the product owner as soon as a story is done.

When something gets in the way of you reaching your most productive modes, something is impeding you. (Examples: the unit tests take more than 30 seconds to run, the IDE is difficult to setup into a productive state, it's hard to setup a pairing station, people/email/IM keep taking you out of your most productive state, you've been pairing too long and you want to disagree with everything your partner is saying so you need a break, you come into work too tired to interact with people because you were up late developing code at home/work.) We're human, sometimes these can't be avoided. If most of the time you can't reach your most productive mode, then something is wrong.

PREPARATION FOR YOUR MOST PRODUCTIVE MODE:
Clarity--
* You should know what is on the sprint backlog. If you're confused about this, then something is dearly wrong! During standup, if you can't see how what someone is saying maps back to the backlog, then ask. If they don't know, then solve the problem: stop working on stuff that's not on the backlog.
* Get those definitions of done for a Sprint and a Release in a clear, easy to understand state. If it has 20 separate items and you need a lawyer, it doesn't help with clarity.
* You should know your velocity by sprint planning for the next sprint.
* At standup, the team members should all understand at some level what each person is saying. If you don't have a clue, say "what's that about?" so you know. Sometimes you'll realize it isn't helpful for person A to recount a blow-by-blow of a meeting about some other concern that has little to no impact to your project. In that case, ask them to parking lot it or follow up after standup with the one other person they are talking to.
* Standups > 15 minutes should be an anomaly. If they aren't then something is wrong. Keep standup focused on the team talking to each other about the three questions. Make it clear when standup is over and your going to shift into something else so people can leave or understand what you are about to go into is a hallway meeting. Otherwise, standups turn into 45 minute hallway meetings every day. Immediately raise impediments during standup about why standup is going too long (trying to do release planning, trying to solve a problem by falling into a 5 minute discussion).
* Use the fist of five. It's simple and effective.
* Come to standup prepared. You may need to make some notes. You may need to meet with a subset of the team *before* standup (the ones which could be a 1-2 on a fist-of-five) and have those long discussions so you have some alignment so standup goes smoother.
* Use big visible charts. If you're team has a problem, then make a chart. If your standups run too long, make a chart of the time. If the team sees the chart, but refuses to adjust despite that, then you need another approach. (Setting an egg timer for two minutes and passing it around to each speaker really works because it provides a quick feedback mechanism). By day three most of them will have figured out how to communicate effectively in that constraint.)


Wednesday, February 18, 2015

Automated Tests for Database Procedures

Why not future-proof your database procedures just as the middle tier and front-end developers have been future proofing theirs? Not only can automated unit tests be built for each procedure but Test Driven Development (the practice of writing a simple unit test that fails and forces you to implement some simple procedure to satisfy the failing test, and once the test passes you enhance the test or add a new unit test to grow the procedure further) can be done as well.

Why Unit Test Procedures?

Every time there's a change in a procedure or schema, unexpected errors can happen. To mitigate disaster, you'll have been doing some kind of testing: manual testing, automated testing, ... 
An early adopter's mistake is to test every possible case you can imagine. For unit testing, this isn't your test target. You're goal is to have every line of procedure be necessary to pass your test procedures. Although this means that some lines of code are tested as a side affect, and that's OK.  When constructing your unit test, focus on testing only the one procedure you're targeting.

Confidence

Without unit tests whose job description is to test each stored procedure, then you're gambling that the testing in other tiers will uncover problems. Why live with this uncertainty? If you have a test suite that confirms every line of procedure works as expected, you'll have supreme confidence that your next release is truly an improvement (rather than new features with new bugs). 

Fast feedback

Since we're writing unit tests that test each procedure in isolation from other procedures (or at least as isolated as possible), then the tests will execute quickly. Likely you can test 100 procedures in a minute which scales to thousands of procedures in thirty minutes. In fact, if you run these tests continuously (triggered by code checkins) or whenever the you feel some uncertainty, you can execute the test suite to ask the question, "do I have a regression?" and get back the answer in less than a minute.

The tests "tell you" the regression's location

With individual unit test (test procedures) designed to test a stored procedure in isolation, you'll have signaling that shows what procedures are fine and which are in failure. This means once there is a regression it the tests will indicate approximately what procedure or procedures to examine.

Tools for Unit Testing Database Procedures

Here are a few that either I've personally used or I read through the documentation and meets my minimum feature list (asserts, pre test execution routines, post test execution routines, outputs a report, allows easy execution of entire test suite).

Oracle

(PLUnit looked promising but isn't maintained any longer, which makes it unusable since it's closed source.)

Oracle SQL Developer has unit testing tools built in (view->unit tests).  It's a bit complicated.  The learning curve to use this tool is higher than PLUnit.  Here are some links about this tool:
http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/sqldev/r30/sqldev_unit_test/sqldev_unit_test_otn.htm

PLUTo is a minimalist setup.  utPLSQL has a rich API.  The Oracle one is hard to get into because Oracle's tech writing is so dull and uninspiring.  And the last time I tried to use it, the tool was disabled for some reason (license issues?).  My favorite is utPLSQL.  It's made popular mention on Steven Feuerstein's (of Oracle) blog as well.  You can install it in minutes and start with the examples.

T-SQL

T.S.T. Sql is a nice simple tool with some getting started videos and an InfoQ article.

Common Test Environment Configurations

To execute automated tests for a DB means you need a DB instance to put the procedures inside of and data for the procedures to execute.  As for data/schema, this should be created (inserted) as part of the automated test.  To answer the question of how many DB instances, there is a range to this answer:  You need enough. :-)

Usually you need:
  • 1 instance for continuous integration, since you're going to want to execute your automated tests continuously.
  • At least one instance for someone to develop automated tests.  Typically, every developer creates an instance on their own system whenever they want to execute, debug, or create automated tests.  If for some number of reasons you can't have an instance for each developer, then you'll need to manage them as a pool.

Test Design

The above tools add some supporting procedures so you can focus on creating automated tests in the form of test procedures.  The job of unit tests is to confirm that the code under tests operates as the developer intended it.
Good automated unit tests have the following characteristics:
  • each test executes in microseconds
  • independent of execution of other tests (said another way, you should be able to execute the tests in any order you wish)
  • prefer having many simple test procedures to test a DB procedure (which are easy to understand and maintain) rather than a few test procedures that check many thing.
  • use test data which is as simple as possible--just enough to make the procedure under test happy.
  • test data should be created either by the test itself
  • test procedure names should express: what procedure they are testing and the test scenario
  • each of DB procedure under test should be tested in isolation (without dependency on other procedures)
System level tests are supposed to answer the question, is feature XYZ working as the user expects it?  These tests will work with large data sets and developing system level tests:
  • each test executes seconds, minutes, or longer
  • independent of other tests
  • destructive tests should undo their "inserts" so as not to affect other tests (could be implemented by either refreshing the data afterwards or not committing the transaction).
  • prefer creating tons of non-destructive tests and few destructive tests so you don't need to often refresh the data which is slow
  • keep destructive tests which require data refresh in a separate test suit so you have a "fast" suite for continuous builds and your "slow" suite for hourly or nightly builds.

Test Data Creation

Ways that test data is created are: 
  • restoring to the database a set of test data.
  • sql script that inserts the data.
  • sql code that creates test data that is used by your test procedures
Your DB instance creation along with schema should be automated as well so that any developer on the team can easily create a DB test environment and so your continuous integration system can recreate the test environment each time it executes.

Wednesday, December 3, 2014

Recommended Behavior Driven Development (BDD) Toolsets

As a consultant who works with many different teams on mostly .Net,  Java and JavaScript projects, let me recommend my favorites.

Cuccumber versus JBehave
I don't have a clear favorite between these two.  The tools between them seems to be about at the same level of maturity (or immaturity).  Both allow you to use JUnit as a test runner.  Both allow Gherkin syntax.  I give an edge to Cucumber in that it needs a little less hand-holding configuration files to get things up and running.

Cucumber
Here is my favorite Cucumber setup which I'm using (as of Mar 2017):

If you just want to download cucumber jars the traditional way:
http://repo1.maven.org/maven2/info/cukes/cucumber-java/1.2.5/
http://repo1.maven.org/maven2/info/cukes/cucumber-junit/1.2.5/
http://repo1.maven.org/maven2/info/cukes/cucumber-core/1.2.5/
http://repo1.maven.org/maven2/info/cukes/gherkin/2.12.2/
http://repo1.maven.org/maven2/info/cukes/cucumber-jvm-deps/1.0.3/
http://repo1.maven.org/maven2/info/cukes/gherkin-jvm-deps/1.0.2/ http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar  http://repo1.maven.org/maven2/junit/junit/4.12/junit-4.12.jar

The above will allow you to develop and execute feature files and BDD automation.  Great for executing using maven and add these external jars to your build so you can build step definitions in Java.  But no sane person would do this without a nice syntax highlighting editor and "open on declaration" goodies plugged into Eclipse.

Natural

Natural is a feature file editor that uses code-assist to fill in Given, When, Then, and allows you to jump to the step definition.  Install Natural from the Eclipse Marketplace found in Eclipse at help->Eclipse Marketplace. Natural itself wasn't tagged in the depot correctly so you'll find it by searching for "cucumber," "jbehave," or several other BDD related tags.  Install it.

Test it out by creating a plain text file with a .feature extension.  I find when creating a new file with a ".feature" extension, I need to close the tab and re-open it so Eclipse can hand off editing the .feature file to Natural.

What Natural does for you when editing a feature file:
  • content assistance in choosing Steps, 
  • F3 (open declaration) which shows the Java definition for the step (assuming one exists), 
  • Outline view, 
  • syntax highlighting, and
  • caution marks for Gherkin steps that don't have a Java definition.




Manual installation
Sometime back, when traveling Asia, I needed to do manual installs as the Eclipse Marketplace and Natural repository were timing out.  In those cases I did manual installs.
https://github.com/rlogiacco/Natural/wiki/Installation-Guide
  1. Using Eclipse Install XText from this location: http://download.eclipse.org/modeling/tmf/xtext/updates/composite/releases/
  2. Download an Eclipse archive (.zip) of Natural from this location: https://github.com/rlogiacco/Natural/releases
  3. In the Eclipse->Install New Software, click "Add..." and this time select "Archive" and select the path to the zip file downloaded in the above step.

But Natural alone won't run your feature tests.  You need to install Cucumber-Eclipse, or as I prefer, run them via "cucumberized" JUnit test cases via @RunWith(Cucumber.class).

Cucumber-Eclipse
I don't recommend this tool as I've never gotten it to work for the last 12 month (2016/2017).  But If you want to give it a go....  As it's not in the Eclipse Marketplace for whatever reason, use help->install new software.  Click Add and add this url:
Select Cucumber-Eclipse and install.

What Cucumber-Ecilpse should do you for you
The context menu will have "Run feature tests" and "Debug feature tests" which should use the Cucumber CLI to execute the selected feature file, showing the test results in the Eclipse Console.  As of 2016/2017, I've not got this feature to work.  I think it can be made to work via fiddling with Runtime configurations.  I've given up on it and execute BDD tests via cucumberized JUnit test cases and JUnit suits.  (Naturally you can do the same with TestNG.) 

Good Organization and Configuration
Ask yourself how many features you'll build this year.  Then ask yourself what those categories look like.  Now go into eclipse and make a heirarchy, something like this: features->, features->.

So sprint by sprint, add your feature files into to that hierarchy and grow the hierarchy as needed.  I suggest representing the hierarchy as a package in the source code alongside the application it's testing.  If your Steps definitions have a strong relationship with their features, then put them alongside the feature files.  If there isn't such a relationship then don't do that.  (People have different feelings about 'global' namespaces of the BDD Steps.)

source/java/com/my/awesome/app
source/java/com/my/features

Most teams hook their JUnit runner to their BDD tests (using JUnit's @RunWith(...).  Put that test class in the features directory and make it responsible for running all your features.
source/java/com/my/features/RunFeatureTests.java

Using the above organization, follow the principle of "keep things that relate, together" and place the step definitions along side the feature files:
source/java/com/my/features/Foo/Foo.feature
source/java/com/my/features/Foo/FooSteps.java
source/java/com/my/features/ShoppingCart/Purchase.feature
source/java/com/my/features/ShoppingCart/PurchaseSteps.java
source/java/com/my/features/ShoppingCart/TakePayPal.feature
source/java/com/my/features/ShoppingCart/TakePayPalSteps.java
source/java/com/my/features/ShoppingCart/TakeVisa.feature
source/java/com/my/features/ShoppingCart/TakeVisaSteps.java

If you have global steps definitions (don't worry about this when starting out), then put that library in the features directory.  If you're driving a UI, you'll need a place to put your page objects too.  (Please avoid testing the UI unless you have to.  Also use the emergent design principle and develop your page objects as you need to.)
source/java/com/my/features/global_steps/*Steps.java
source/java/com/my/features/page_objects/Login.java
source/java/com/my/features/page_objects/ProductPage.java

SpecFlow
For .Net, all I ever seem to use is Spec Flow and it works good enough.  Here are some pretty good directions.  (FYI, don't believe him that this will work for Express versions of VS.Net as Microsoft turns off useful things like plug-in installation and debugger .)  The main thing is you need to install two things: SpecFlow libraries, and SpecFlow templates (for editing .feature files).

Tuesday, July 8, 2014

Don't forget to AGILE your Test Plan when transitioning from Waterfall to Scrum

Goal: Repeatable quality through automated tests!

But we need people to develop them. Traditional organizations call these people testers.


Tester-> Automated Tests!

In trad. organizations, testers rarely do this because of the traditions of Waterfall.

Tester-> Test Plan -> Automated Tests!

And this is where the trouble starts. Due to the divide-and-conquer and handoff approach of Waterfall, it made sense to split the role of software development into programmer and tester (I'll not debate the pros and cons of doing this, Agile comic SCRUM NOIR—A Silo to Hell! does a nice job.) but in the Agile context, these testers are challenged in integrating their work with a Scrum team: they can't write automated tests until late in the Sprint. This is a big problem when moving to a practice such as Acceptance Test Driven Development where automated test development starts on the first day of the Sprint.

Iterative Testing Problems:
  1. Testers don't plan together with the developers during Sprint planning.
  2. Testers never check-in an automated test on the first day of the Sprint.
  3. Test Planning isn't done continuously (a little bit here, a little bit there, and then executed, then repeat) but instead is an upfront event that takes up 50% or more of the Sprint.
  4. Testers complain they don't have enough information to get started.
The above happen in organizations in transition to Agile where people carry old habits and behaviors to their new roles, even if the behaviors aren't optimal. The Waterfall process was planning heavy and everyone (testers, developers, ...) were encouraged to spend a few months writing documents and reviewing them, creating a false sense that we "planned well." (The security was demonstratively false since the plans between waterfall phases always changed.) Since test and development are often in separate organizations, they coordinate around events set on calendars to deliver artifacts: Test Plans (among other things). The tester is responsible for the Test Plan and had dependencies on pretty near everything in order to produce it (development, architecture, business requirements, ...).

This habit is antithetical to the Scrum process since a Scrum team is doing incremental delivery of product and doesn't know until Sprint Planning what will be done during the next Sprint. This forces the Testers to produce Test Plans under immense stress if they preserve old habits.

This results in:
  1. Testers hating Agile.
  2. The Test part of the organization hates Agile and starts working against change initiatives.
  3. Testers complain that they have to drive everything because the tester's need becomes the event rather than a scheduled milestone.
  4. Many preconditions to creating a Test Plan: Testers demanding a lot of input documentation from other roles (design specs, arch specs, use cases, business case studies, hardware diagrams, call-flow, process flow,...) before they feel they can complete their Test Plan.
  5. Equating Incremental testing with incomplete testing: Tester's consider their Test Plans incomplete because they are only supposed to think of testing the functionality they are delivering that Sprint rather than for the entire release.
Points 1 and 2 are effects which are mitigated by showing them how to be successful. Point 3 is discomfort about the culture change from Waterfall, where the process drives the events, into an Agile process where individuals drive the process. Testers and those who support Test Plan creation get used to it after a few Sprints. Point 4 is a "process over working software" habit from Waterfall where if testers (or their management) feels rushed, they can buy more time by demanding more process and documentation from others as dependencies. Point 5 requires another change in thinking which will happen after doing a few Sprints, witnessing that small high quality subfeatures will sum up to a large high quality feature.

If you change your process without changing how you do things then nothing's going to change (except for the labels). So points 3 and 5 are natural to "storming" (Tuckman model) and must be allowed to happen. Once we get to later steps, "norming" and "performing," and do it say in 3 Sprints, the dangers of the change rejection (points 1 and 2) will go away. Point 4 is a deep culture change which takes time until people to understand the Agile Manifesto Values and Principles, namely, Working Software is the primary measure of progress (automated tests are working software) rather than process checkpoints, milestones, and documentation completion.

No matter what, an organization in transition will have storming and that is healthy if conflicts are allowed to be exposed AND resolved (healthy stress/conflict drives change). To help "storm well," here are some activities.

How to Agile your Test Plan

The Scrum team containing programmers and testers must re-invent how they work together and be open to new ideas and ditch some bad ones (the heavy weight, comprehensive test plan). Each story needs it's own Test Plan. Look at solving this problem at two levels: Test Plan format and timing.

Making the format you already have, lightweight (format)

Rather than introduce any additional process/methodologies, make what you already do lightweight. If your usual Test Plans are 10-20 pages for features completed during a multi-month release, try and do the same plan but on one sticky for one User Story.

How can one stick get results as good as multipage test plans? We're leveraging the fact (and would be foolish not to) that within a few days we'll be building small features, so we don't need to document so heavily.

Agile Context (and why Agile development really is different than Waterfall):
  • a lot of information is successfully retained in our tacit knowledge since we are working on a small team that interacts daily,
  • we are dedicated to one sprint backlog and become experts in its execution,
  • we'll start acting on our plan within days,
  • we're working on sub features and only need to test the sub features we are doing this Sprint, and
  • each User Story is independent of the others so each must be tested independently
  • the majority (if not all) of the tests will be automated and checked in and will be our best documentation and reporting system
If you argue that your automated tests cannot act as your documentation, then you'd better work on your test design because you've got a problem that must be resolved.

Limber the mind

To change the results of your work you need to change yourself. A lot of what stops us are habits learned during the Waterfall context which need to be shed so we can develop sensible ones for the Agile context. This problem affects anyone when changing work contexts: I'm a science fiction author who spends hours getting my words right who sometimes spends hours getting an email right. This is complete waste for a one-off email. I had to learn that when I write technical planning documents or emails to reel myself back since prose isn't necessary. It took conscious effort to shift gears and doing pair work with another helped.

To do so I had to:
  • decide it was important to change,
  • be open to new ideas, in fact, be open to trying something so crazy it couldn't possibly work and then go for it.
James Whittaker of Google has a great facilitation style called The 10 Minute Test Plan which breaks down mental barriers that prevent writing a good and quick Test Plan.

Acceptance Criteria (format)

Acceptance Criteria are the most lightweight and commonly used of all Test Plan formats: a simple bullet list of what the application should do before the PO will accept the User Story.




Acceptance Criteria can also take the format of wire frames, call flows, non functional requirements, ....
Each User Story should have acceptance criteria before going into Sprint Planning. More can be added at any time, but it's important to have a rough list before Sprint Planning or the meeting will become overloaded and slow.
Each User Story should have acceptance criteria before going into Sprint Planning. More can be added at any time, but it's important to have a rough list before Sprint Planning or the meeting will become overloaded and slow.

4D Analysis (format)

4D Analysis was introduced to one of my teams by friend and fellow coach XuYi. 4D adds three dimensions of additional analysis to simply using Acceptance Criteria. Adding more analysis isn't necessarily a good thing because that's what got us the 20 page Test Plan. However 4D is still one page and maybe your team'll find working on the first 3Ds helpful before getting to the Acceptance Criteria. The 4D analysis is attached behind each user story.
The Process dimension is further broken down into 3 types:
  • User workflow (how it works from a User's perspective)
  • Business process (how it works from a Business Analysis perspective)
  • Technical flow (system engineer or architecture view)
The idea is that for an individual User Story you'll need one of the above process types and rarely, you'll need more than one.

Strangely enough, the feedback I've received from teams doing 4D Analysis is that despite the single sheet of paper, the amount of analysis is greater than they were used to from their traditional multipage test plan. Customize the 4D analysis to fit your team's needs.

BDD (process, format, and technology)

Get your PO adding Behavior Driven Development scenarios to your User Stories. Or at a minimum work with your PO and get them written down. Good BDD tests make wonderful test plans AND automated Tests AND traceability documents!

Given there exists bad entries in [playlist]
When trying to play this playlist
Then remove invalid playlist entries

examples:
|playlist|
|Never Played|
|My Top Rated|
|Whole Library|

More BDD articles:Well written BEHAVIOR Driven Development Scenarios, BDD Practices that Maximize Team Collaboration and Reduce Risk.

Timing

When should Test Plans be created? The two strategies are:
  • Create Test plans during the Sprint
  • Create Test plans before Sprint Planning.
The testers and developers include in their estimates made during Sprint planning the effort to create Test Plans and implement tests. But they need to learn to move fast and test like a jazz band rather than a symphony which has a conductor that has organized a lot of planning and process.

Lightweight test plans can be created before the Sprint by leveraging Backlog Grooming. Here's an agenda that broke backlog grooming up into the following: 30 minute kickoff, offline (outside of meeting) collaborative work, 1 hour grooming meeting.

Here's an example calendar for a three week Sprint:

MTWTF MTWTF MTWTF
         ^- Kickoff Preperation for Grooming
            ^- Groom results for 1 hour

Constraints:
  • a team spends no more than 10% of a Sprint preparing for the next Sprint
  • other than Sprint Demo and Retro, avoid meetings on last 2 days during Sprint crunch time
  • have Grooming far enough in advance of Sprint Planning to fix problems uncovered in Grooming
Kickoff Agenda (team, PO, SMEs in attendance) < 30 minutes
  • During meeting
    • PO brings proposed Sprint Backlog
    • Team members select stories to prep for grooming and are encouraged to collaborate with other team members
    • Decide what stories need SME deliverables/support and make that status visible
  • Offline, to be finished by Grooming Meeting start (Monday 2PM)
    • Fill out prep document
      • User Scenarios {Functional flow, User Experience behavior} (done by: programmer or tester)
      • Y/N needs SME deliverables (architecture view, etc.)  (roles: tester, SME)
      • Refine User Story Acceptance Criteria (roles: everyone)
      • Update Assumptions (roles: everyone)
    • PO and SME will visit each team member (individuals and interactions per the Agile Manifesto) before Grooming Meeting and see how they can help.
    • ScrumMaster will make sure the process is successful and that everyone comes to the Backlog Grooming meeting prepared.
Grooming Meeting 1hour, review the results of the prep work as a group.
A team reviewing User Stories and grooming prep doc. They are standing up during the action moments for maximum collaboration. Stand up meetings are 30% faster than their "sit down" counterparts.

During Sprint Planning, the team will adjust further and are expected to refine further even during the Sprint.

Summary

Goal: Automated Tests!

But we need people to develop them.

Ideal:
Tester->Automated Tests!

Usually, teams do at least a lightweight Test Plan: 
Tester-> Acceptance Criteria-> Automated Tests
Tester-> BDD-> Automated Tests
Tester-> 4D Analysis -> Acceptance Criteria -> Automated Tests 

Some teams need more analysis. Find a way to do it using only 10% of your current Sprint to plan for you next Sprint:
Tester->Test Plan->{Acceptance Criteria, BDD, 4D Analysis}-> Automated Tests

Remember you're doing Test Plans to have automated test cases to defend your product from regression. Your Test Plans should be designed to serve this purpose. Having large Test Plan documents was never the goal. If you can produce 2-6 automated test cases from a one page Test Plan, and spend no more than 10% of your Sprint doing Test Plans, then you're on the right track.