Magnus Axelqvist

Magnus Axelqvist

No fluff, just stuff

“Done” is often “Waste In Progress”

My experience is that most Scrum teams define "Done" as a "potentially shippable" story/feature. However, Lean has taught us that this definition actually introduces waste in the software development process.

I like to think of such a "Done" column as "Waste In Progress" and should thereby also have a limit. So, once the waste limit has been reached, it is time to merge shippable stories to the current release branch and deploy a new version to production.

Hopefully I will be able to test this idea in my current team. 🙂

Turn your external screen into the primary one in Ubuntu

Just enter xrandr to get hold of the display names. Then enter xrandr –output <display name> –primary i order to make your external screen the primary one. Done! See example below:

magnus@gollum:~$ xrandr
Screen 0: minimum 320 x 200, current 3600 x 1200, maximum 8192 x 8192
VGA-0 disconnected (normal left inverted right x axis y axis)
LVDS connected 1680×1050+1920+0 (normal left inverted right x axis y axis) 331mm x 207mm
   1680×1050      60.6*+
   1400×1050      60.0 
   1280×1024      59.9 
   1440×900       59.9 
   1280×960       59.9 
   1280×854       59.9 
   1280×800       59.8 
   1280×720       59.9 
   1152×768       59.8 
   1024×768       59.9 
   800×600        59.9 
   848×480        59.7 
   720×480        59.7 
   640×480        59.4 
S-video disconnected (normal left inverted right x axis y axis)
DVI-0 connected 1920×1200+0+0 (normal left inverted right x axis y axis) 518mm x 324mm
   1920×1200      60.0*+
   1600×1200      60.0 
   1280×1024      75.0     60.0 
   1152×864       75.0 
   1024×768       75.1     60.0 
   800×600        75.0     60.3 
   640×480        75.0     60.0 
   720×400        70.1
magnus@gollum:~$ xrandr –output DVI-0 –primary
magnus@gollum:~$

Turn your Selenium tests into DSL-based acceptance tests in Fitnesse

  1. Download the Fitnesse jar from http://fitnesse.org/FrontPage.FitNesseDevelopment. Move the jar to e.g. /usr/local/fitnesse.
  2. Download the Selenium Server jar from http://seleniumhq.org/download/ and move the jar to e.g. /usr/local/selenium.
  3. Start the Selenium server (will listen to port 4444 by default):
    cd /usr/local/selenium/ ; java -jar ./selenium-server.jar -log ./selenium-server.log
  4. Start the Fitnesse server (will listen to port 80 by default, but you can override this setting using the -p option):
    cd /usr/local/fitnesse/ ; java -jar ./fitnesse.jar -p 8080
  5. In a shell, create a new jar-project in e.g. ~/projects/:
    mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.fitnesse -DartifactId=mywebtest
  6. Goto ~/projects/mywebtest and add the following dependencies to the pom.xml:
    <dependencies>  <dependency>    <groupId>org.testatoo.openqa</groupId>    <artifactId>selenium-java-client-driver</artifactId>    <version>1.0.2_20090715</version>  </dependency>
    
      <dependency>    <groupId>org.fitnesse</groupId>    <artifactId>fitnesse</artifactId>    <version>${fitnesse-version}</version>  </dependency>
    
      <dependency>    <groupId>org.fitnesse</groupId>    <artifactId>fitlibrary</artifactId>    <version>${fitnesse-version}</version>  </dependency>
    
      <dependency>    <groupId>net.sf.webtestfixtures</groupId>    <artifactId>webtestfixtures</artifactId>    <version>2.0.1.3</version>  </dependency> <dependencies>
  7. For convenience, enable jar artifact with dependencies by adding the following plugin to your pom.xml:
    <plugins>  <plugin>    <artifactId>maven-assembly-plugin</artifactId>    <version>2.2</version>    <configuration>      <descriptorRefs>        <descriptorRef>jar-with-dependencies</descriptorRef>        </descriptorRefs>       </configuration>    <executions>      <execution>        <id>make-assembly</id>         <phase>package</phase>         <goals>          <goal>single</goal>         </goals>      </execution>    </executions>  </plugin></plugins>
  8. (Optional) For Eclipse users, create project file for mywebtest:
    mvn eclipse:eclipse
  9. Create your WebTest fixture class, using your favorite editor (that is, Eclipse :-)):
    package com.mycompany.fitnesse;   import com.neuri.webfixture.WebTest; public class MyWebTest extends WebTest {}
  10. Build the jar artifact and copy the jar to /usr/local/fitnesse/
    mvn install ; cp target/mywebtest-1.0-SNAPSHOT-jar-with-dependencies.jar /usr/local/fitnesse
  11. Goto http://localhost:8080 and click the “Edit” link. Add the text MyTest and click save.
  12. Click on the question mark next to your new test, add the following text and then save (the backslash below denotes only that the line continues on the next line and should not be part in the actual test specification):
    !define TEST_RUNNER {fitlibrary.suite.FitLibraryServer}!path mywebtest-1.0-SNAPSHOT-jar-with-dependencies.jar!path lib/*.jar!|com.mycompany.fitnesse.MyWebTest||Start Browser |firefox|With Selenium Console On|localhost|At     Port|4444|And Scripts At|http://www.amazon.com/||user opens URL | / || user adds the book with title | Fit for Developing Software:     Framework for Integrated Tests | to the shopping cart || the shopping cart should contain a book with title | Fit for     Developing Software: Framework for Integrated Tests || the shopping cart should contain | 1 | item |

    The test specification

  13. Click on properties and change the page property from Normal to Test. Then click on “Save properties”.
  14. Run the Fitnesse test by clicking on the Test button located at localhost:8080/MyTest. You will get exceptions like (see image):No test methods implemented
  15. Add the missing methods to the class MyWebTest:
    public class MyWebTest extends WebTest {   public void userAddsTheBookWithTitleToTheShoppingCart(String title) {  }   public boolean theShoppingCartShouldContainABookWithTitle(String title) {    return false;  }   public boolean theShoppingCartShouldContainItem(int numOfItems) {    return false;  }}
  16. Build the jar artifact again and copy the jar to /usr/local/fitnesse/:
    mvn install ; cp target/mywebtest-1.0-SNAPSHOT-jar-with-dependencies.jar /usr/local/fitnesse
  17. Run the Fitnesse test again and see the difference.After stub methods have been implemented
  18.  We need now to implement the test methods, using the the primitive operations offered by the base class WebTest:
    public void userAddsTheBookWithTitleToTheShoppingCart(String title) {
      userOpensURL("/");  waitSecondsForElementToAppear(5000, "navSearchDropdown");  userSelectsFrom("label=Books", "searchDropdownBox");  userTypesIntoField(title, "twotabsearchtextbox");  instance.submit("site-search");  pageReloadsInLessThanSeconds("30");  userClicksOn(title);  waitSecondsForElementToAppear(30000, "bb_atc_button");  userClicksOn("bb_atc_button");}
    
    public boolean theShoppingCartShouldContainABookWithTitle(String title) {  userClicksOn("Cart");  waitSecondsForElementToAppear(5000, "cartViewForm");  return pageContainsText(title);}
    
    public boolean theShoppingCartShouldContainItem(int numOfItems) {  userClicksOn("Cart");  waitSecondsForElementToAppear(5000, "cartViewForm");  String actualValue = this.instance.getValue("quantity.1");   return numOfItems == Integer.parseInt(actualValue);}
  19. Build the jar artifact again and copy the jar to /usr/local/fitnesse/:
    mvn install ; cp target/mywebtest-1.0-SNAPSHOT-jar-with-dependencies.jar /usr/local/fitnesse
  20. Run again and the test should be all green 🙂Test methods have been implemented

One detail I have not mentioned is how-to know which elements to use in the test. I used Firebug in combination with Selenium IDE to get hints of what elements I could use. In this particular example, the Selenium IDE produced the following test class:

     @Test     public void testAmazon() throws Exception {       selenium.open("/");       selenium.select("searchDropdownBox", "label=Books");       selenium.type("twotabsearchtextbox", "Fit for Developing Software:           Framework for Integrated Tests");       selenium.click("//input[@type='image']");       selenium.waitForPageToLoad("30000");       selenium.click("link=Fit for Developing Software: Framework for           Integrated Tests");       selenium.waitForPageToLoad("30000");

       for (int second = 0;; second++) {         if (second >= 60) fail("timeout");         try { if (selenium.isElementPresent("bb_atc_button")) break; }          catch (Exception e) {}         Thread.sleep(1000);       }

       selenium.click("bb_atc_button");       selenium.waitForPageToLoad("30000");       selenium.click("link=Edit your Cart");       selenium.waitForPageToLoad("30000");       verifyTrue(selenium.isTextPresent("Fit for Developing Software:           Framework for Integrated Tests"));       verifyEquals("1", selenium.getValue("quantity.1"));     }

For most of the operations, I was able to use corresponding WebTest operations that are of a slightly higher abstraction level. However, to submit the search for books, I used the Selenium instance directly, since the form had a more readable id (“site-search”). In order to get hold of the Selenium instance, I needed MyWebTest to inherit from WebTest (painful, since I prefer composition :-))

As you may have noticed, I needed to add wait statements. Thus, the problem with brittle Selenium tests is still there. However, I believe Fitnesse test is more readable compared to the Selenium test. In addition, the tests can be modified by a non-programmer and understandable by business people. Thus, tests like these can bridge the gap between customers, business people, developers and testers. Once you have developed your own DSL (Domain-Specific Language), you’re ready to write acceptance test first together with the stakeholder/product owner. That is, you’re able specify executable specifications before the actual functionality is in place, which is very attractive to a test-driven addict  as myself :-).

What remains is to include the Fitnesse tests in your the CI server. But that is another blog entry to be written. 🙂

Let TellStick tell you when you’re in trouble

Here follows a crash course how-to visualize the health of your CI server or live system.

  1. Buy a TellStick from Kjell & Company,  http://www.kjell.com/content/templates/shop_main_details.aspx?item=50200&path=&sms_ss=favorites&at_xt=4d336e97c742b49d,1.
  2. Buy a remote switch from Kjell & Company, http://www.kjell.com/content/templates/shop_main_details.aspx?item=50219&path=&sms_ss=favorites&at_xt=4d336ec00712cf8f,0.
  3. Buy your favorite lava lamp/warning light that will indicate the status of your project/live system.
  4. Install the TellStick software as described at http://www.telldus.se.
  5. Add the configuration for your remote switch to /etc/tellstick.conf (see example below). Remember to configure the remote switch in the same way.
  6. Write a program/script that turn on/turn off the remote switch depending on the status of your project (see example below)
  7. Optional, add the program to crontab in order to check the status at regular intervals (see example below).
  8. Done 🙂


tellstick.conf

deviceNode = "/dev/tellstick"
device {
  id = 1
  name = "enterprise"
  protocol = "risingsun"
  model = "codeswitch"
  parameters {
    house = "1"
    unit = "1"
  }
}



check_enterprise.sh

#!/bin/sh

success=`wget -qO – –http-user=<user> –http-password=<pwd> –auth-no-challenge https://<base>/hudson/job/enterprise/lastBuild/  | grep ‘Success’`
failed=`wget -qO – –http-user=<user> –http-password=<pwd> –auth-no-challenge https://<base>/hudson/job/enterprise/lastBuild/  | grep ‘Failed’`

if [ ! -z "${success}" ]; then
        tdtool –on ‘enterprise’
fi

if [ ! -z "${failed}" ]; then
        tdtool –off ‘enterprise’
fi



crontab entry:

* 8-16 * * 1-5 /home/magnus/bin/cron/check_enterprise.sh



A good day at work 🙂

The Wicket framework is not TDD-friendly

The Wicket framework is somewhat deceptive when it comes to testing, especially TDD. The wicket tester is pretty good for integration tests. However, when trying to test individual components in a TDD manner, you’ll get bitten by the “final” keyword that appears quite frequently among the Wicket components. Mockito won’t help you, my favorite subclass-and-override technique cannot be applied. So, you’re on your own, implementing extra methods in order to get the component under test, which leads to frustration and lack of focus.