A Software Commons

February 11th, 2009

Where are the places where all stakeholders can meet? Not a physical place, but artifacts, tools, etc.

Assuming that our stakeholders are comprised of customers, developers, testers, database, support, and deployment working in their own silos, what is the common ground between any two?

Worst case:

Customer Developer Tester Database Suppport
Customer - Requirements Requirements Requirements Requirements
Developer Application - Application DB Schema Application
Tester Bug Report Bug Report - Bug Report Bug Report
Database DB Schema DB Schema DB Schema - DB Schema
Support Application Application Application DB Schema -

We can see that in a worst-case, siloed organization, the conduit for communication can differ. Even between two stake holders, the conduit can differ depending on the flow of information (e.g., the conduit between Customer and Support is not the same as Support and Customer). Each conduit is a chance for miscommunication.

So, the common ground between any two can vary. What if we have an idea or issue that spans several silos? More and possibly very different artifacts will have to be taken into account. Because these artifacts were created by different groups, there’s a good chance there is going to be miscommunication and wasted effort.

Now, let’s tweak the terms like “Requirements”, “Application”, “Bug Report”, and “DB Schema” for a best-case description of said artifacts/conduits:

Requirements: Description of what the Application should do with runnable examples and text
Application: The system that will be deployed for users, as well as all the tests, set up scripts, etc
Bug Report: Automated, report-as-soon-as-you-find-it test failure
DB Schema: The DDL and DML used in the database in support of the Application

What we really need is something that takes the best-case description of the artifacts and holds them in a common area for all of the stake holders. This common area would be the spot where we all can talk the same talk, manipulate the necessary artifacts, and if need be, see the appropriate “view” (as a Customer, as Tester, etc…) of the software as a whole.

Where/what is this commons? Well, it doesn’t fully exist yet. Things like Fit, FitNesse, and BDD almost get us there. The next generation of tools such as Twist get us even closer.

Extension is about Consumption

February 11th, 2009

The next time you are about to extend a class, stop and think about who is going to be consuming this extended class. If the extended class (instead of the base class) is in the contract amongst collaborators, why the extension?

If, somewhere along the line, you want your extended class to be used (consumed) as the base class, go ahead and extend. If that isn’t the case, then maybe composition should be preferred.

It really comes down to this:

Extension is about consumption.

Disconnect!

February 4th, 2009

Quick–how many of your tests would fail if you were not connected to a network (for database, files, services, etc)? How many of these are labeled as “unit tests”?

Do you have a way of quickly determining which tests are dependent upon that network connection? Can you easily run all the tests that aren’t dependent upon the network? Do you find that there are errors/failures in surprising areas?

Try it and see. You may learn something interesting about your code’s dependencies.

Purge!

February 2nd, 2009

Quick–when was the last time you just deleted the directory for you project(s)? Could you do it right now without any problems? What would you need to recreate your set up?

Once you have your setup, it seems pointless to spend any more time trying to make it easier/faster to create said setup. And maybe it is for *you*. But, the next person coming along probably won’t consider it pointless.

Be hardcore. Purge that stuff right now and see what you need to do to get going again. You’ll find out quickly what you (and your new team member, your CI, your deployment team, etc) need.

First Principles

January 13th, 2009

I was talking to a friend the other day about agile philosophy and practices. We were talking about priniciples leading to actions, which in turn, lead to other principles.

He related an opinion he had received regarding the most important agile principle:

A commitment to continual improvement

Or taken from the Principles behind the Agile Manifesto:

At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

I believe that if we are serious about producing software that meets our customers’ needs, all other practices and ideas can be traced back to this. If you can’t trace a practice back to continual improvement, or if a practice/principle leads to an improvement, but cannot be extended, then you aren’t going to see real, lasting, long-term improvement.

Too often, when we tackle a larger-scale problem–say something that is at a multi-team level–we don’t keep the idea of continual improvement in mind. Decisions are made that don’t take into account that we want to be able to improve even more sometime in the future. This leads to periods of improvement, followed by a plateau, followed by some backtracking, and then a new improvement.

If we want to reduce this plateau/backtracking, we must keep in mind that we want our decisions to be in accordance with our need to constantly improve.

DRY — Not just for code

January 9th, 2009

Don’t repeat yourself. It is a great advice for writing code. However, it isn’t the only place it is applicable.

Let’s look at a super simple description of software development roles and their artifacts:

Customer: requirements, acceptance tests
Developer: code, unit tests, module tests, acceptance tests
Tester: module tests, acceptance tests

See the overlap? If customers, developers, and testers aren’t working together, we are creating waste through duplication. Even if we are working together, we can do better.

What if worked in such a way that the customer requirements can be run as the acceptance tests and acceptance tests can be viewed as customer requirements? What if architectural requirements can be run as unit tests or module tests? Or, vice-versa?

You can see where I am going with this. We are still creating a lot of waste because of duplication. If we can work within some framework (that doesn’t necessarily mean a tool) that seamlessly allows us to have requirements as tests and the other way around, and reuse tests between customers, testers, and developers, we can make some real gains in efficiency.

Furthermore, working in this manner reduces duplication in communication. Everybody is working with the same “stuff”. This “stuff” serves as documentation as to the expected behavior and real behavior of the system. There should be less time spent talking about the same thing amongst the various roles.

We are all essentially working on the same “stuff”. So, why not act like it and identify areas of duplication and reuse?

JBehave/Selenium Example

December 21st, 2008

In a previous post I went through the mechanics of creating a simple JBehave test. This time around, I want to do something a little more “real”.

So, let’s make another simple example that uses Selenium. That way, we have real feel for the mechanisms we would use.

We’ll start once again with our scenario:

Given I am on “http://www.bitmotif.com”
When I click on link “Test Page For Selenium Remote Control”
Then the title is “Bit Motif ยป Test Page For Selenium Remote Control”

This scenario needs to be saved in a file named “navigation_scenario”.

Using the same approach we took in the previous post, we’ll create our scenario:

package com.bitmotif.jbehaveexamples.part.two;

import org.jbehave.scenario.Scenario;

public class NavigationScenario extends Scenario {
   public NavigationScenario() {
      super(new NavigationScenarioSteps());
   }
}

And, we’ll create our scenario steps:

package com.bitmotif.jbehaveexamples.part.two;

import org.jbehave.scenario.steps.Steps;
import org.jbehave.scenario.annotations.*;
import org.junit.Assert;

public class NavigationScenarioSteps extends Steps {
   private SystemUnderTest system;

   @BeforeScenario
   public void startSystem() throws Exception {
      system = new SystemUnderTest();
      system.start();
   }

   @AfterScenario
   public void stopSystem() throws Exception {
      system.stop();
   }

   @Given("I am on \"$url\"")
   public void startOnUrl(String url) {
      system.open(url);
   }

   @When("I click on link \"$linkText\"")
   public void clickLink(String linkText) {
      system.clickLink(linkText);
   }

   @Then("the title is \"$title\"")
   public void checkTitle(String title) {
      Assert.assertEquals(title, system.getCurrentTitle());
   }
}

This time around we need to make certain we have the ability to start and stop our system. We annotate the starting and the stopping of the system, so we know the state of the system when we run.

Like I said before, we have a system under test that is “real”. In this particular case, our system is really a pass-through to Selenium Remote Control:

package com.bitmotif.jbehaveexamples.part.two;

import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.DefaultSelenium;
import org.openqa.selenium.server.SeleniumServer;

public class SystemUnderTest {
   private static final String MAX_WAIT_TIME_IN_MS = "60000";
   private static final String BASE_URL = "http://www.bitmotif.com";

   private Selenium selenium =
      new DefaultSelenium("localhost", 4444, "*firefox", BASE_URL);
   private SeleniumServer seleniumServer;

   public void start() throws Exception {
      seleniumServer = new SeleniumServer();
      seleniumServer.start();
      selenium.start();
   }

   public void stop() {
      selenium.stop();
      seleniumServer.stop();
   }

   public void open(String url) {
      selenium.open(url);
   }

   public void clickLink(String linkText) {
      selenium.click("link=" + linkText);
      selenium.waitForPageToLoad(MAX_WAIT_TIME_IN_MS);
   }

   public String getCurrentTitle() {
      return selenium.getTitle();
   }
}

With this in place, we can run our scenario. Tres cool.

Be Glad It Is Difficult

December 9th, 2008

In the past couple of months, I have run into a few nay-sayers while attempting to build some test infrastructure. Many times, when I propose a change, the response I get is basically this:

We could probabaly do that, but it would be hard.

Well, duh. That is why we get paid. If it was easy, we wouldn’t have a job. If at any given time you know the solution to all the problems facing you at work, you can be automated out of a job.

Maybe the reluctance is a form of job security. But, I don’t think that holds, either. Why? Because there are always problems to solve. Solving a difficult problem frees you up to solve even more difficult problems. If you are always doing that, I don’t think you’ll have a hard time keeping your job.

Now, I’ll do the disclaimer-type thing. I am not saying we should do something just because it is hard to do. But, in life many things worth doing are difficult. And, if somebody doesn’t know how to do this difficult thing, they hire people like us.

So, be glad it is difficult.

JBehave Rave

November 30th, 2008

I attempted to use JBehave almost a year ago, but found it difficult to work with. In the last two months, however, JBehave 2.0 and JBehave 2.1 were released. These releases represent a fundamental change in how JBehave works, and are supposed to make using JBehave easier. I thought I’d try JBehave again. And, man oh man, it is so much better! Here are my notes.

Getting Started
In order to use the latest JBehave you need to be using Java 1.5 or greater. If you want to use JBehave with your IDE, you’ll need to make sure you are using JUnit 4. You can download JBehave here.

Creating the Tests
We’ll create a text file for the scenario using the words Given, When, Then and And.

Given the basic data set exists
When I do the basic work action
Then the basic result occurs

We need to save the scenario in file. The file should have a meaningful name, but use lowercase letters and underscores, eg: basic_work_scenario

Let’s develop a simple heuristic: basic_work_scenario describes some basic work scenario. Something happens. Causing other things to happen. One step leads to another.

In our code, then, we need a class that reflects the name of the text file:

package com.bitmotif.jbehaveexamples;

import org.jbehave.scenario.Scenario;

public class BasicWorkScenario extends Scenario {
}

With that in place, we should be able to run the scenario. In your IDE, select the BasicWorkScenario class and run it.

If you see something like

org.jbehave.scenario.errors.ScenarioNotFoundException:
Scenario com/bitmotif/jbehaveexamples/basic_work_scenario could not be found by classloader sun.misc.Launcher$AppClassLoader@a9c85c

That means the text file with the Given/When/Then could not be found. The easiest way to do this is to make sure the file is placed along with the compiled classes. In Intellij, I just set the compilation option to take anything: *?.

Now, when we run, we see something like this

Scenario:

Given the basic data set exists (PENDING)
When I do the basic work action (PENDING)
Then the basic result occurs (PENDING)

We now have an outline of what we expect to see, as well as what has been implemented in the scenario. We haven’t implemented anything, so it is still pending. Also, note that you got a green bar.

Let’s continue developing our heuristic. Scenarios have steps, right? So, in our case the BasicWorkScenario has steps BasicWorkScenarioSteps. We need to create BasicWorkScenarioSteps. And, it turns out in JBehave, steps are a type. So, we also have:

package com.bitmotif.jbehaveexamples;

import org.jbehave.scenario.Scenario;

public class BasicWorkScenarioSteps extends Steps {
}

We can integrate our BasicWorkScenarioSteps with our BasicWorkScenario like this:

package com.bitmotif.jbehaveexamples;

import org.jbehave.scenario.Scenario;

public class BasicWorkScenario extends Scenario {
   public BasicWorkScenario() {
      super( new BasicWorkScenarioSteps() );
   }
}

If we run this, we still get a green.

We still don’t have anything interesting. Our BasicWorkScenarioSteps needs to contain the steps needed for the scenario. This translates to:

package com.bitmotif.jbehaveexamples;

import org.jbehave.scenario.steps.Steps;
import org.jbehave.scenario.annotations.Given;
import org.jbehave.scenario.annotations.When;
import org.jbehave.scenario.annotations.Then;

public class BasicWorkScenarioSteps extends Steps {
   @Given("the basic data set exists")
   public void createBasicDataSet() {
   }

   @When("I do the basic work action")
   public void basicWorkAction() {
   }

   @Then("the basic result occurs")
   public void checkResult() {
   }
}

Note the annotations and how they tie to our original text. If we run the scenario, we still get a passing run. Let’s see something interesting. What happens if we put in assertions that fail?

package com.bitmotif.jbehaveexamples;

import org.jbehave.scenario.steps.Steps;
import org.jbehave.scenario.annotations.Given;
import org.jbehave.scenario.annotations.When;
import org.jbehave.scenario.annotations.Then;
import org.junit.Assert;

public class BasicWorkScenarioSteps extends Steps {
   @Given("the basic data set exists")
   public void createBasicDataSet() {
      Assert.assertTrue(false);
   }

   @When("I do the basic work action")
   public void basicWorkAction() {
      Assert.assertTrue(false);
   }

   @Then("the basic result occurs")
   public void checkResult() {
      Assert.assertTrue(false);
   }
}

When we run this, we get the following:

Scenario: 

Given the basic data set exists (FAILED)
When I do the basic work action (NOT PERFORMED)
Then the basic result occurs (NOT PERFORMED)

java.lang.AssertionError:
	at org.junit.Assert.fail(Assert.java:91)
	at org.junit.Assert.assertTrue(Assert.java:43)
	at org.junit.Assert.assertTrue(Assert.java:54)

That’s a little more interesting! Note that after the first failure, the subsequent steps are not run.

Now, let’s hook up our scenario to a “real” system. For our purposes, we have two pieces we need to hook in: the system under test, and our data source. We’ll create these:

package com.bitmotif.jbehaveexamples;

public class StubbedDataSource {
   private boolean basicDataSetCreated = false;

   public boolean createBasicDataSet() {
      basicDataSetCreated = true;
      return true;
   }

   public boolean isInBasicState() {
      return basicDataSetCreated;
   }
}

And

package com.bitmotif.jbehaveexamples;

public class StubbedSystem {
   private boolean actionWasSuccessful = false;

   public boolean performBasicWorkAction() {
      actionWasSuccessful = true;
      return true;
   }

   public boolean isInBasicState() {
      return actionWasSuccessful;
   }
}

We’ll need to modify BasicWorkScenarioSteps like this:

package com.bitmotif.jbehaveexamples;

import org.jbehave.scenario.steps.Steps;
import org.jbehave.scenario.annotations.Given;
import org.jbehave.scenario.annotations.When;
import org.jbehave.scenario.annotations.Then;
import org.junit.Assert;

public class BasicWorkScenarioSteps extends Steps {
   private StubbedSystem system = new StubbedSystem();
   private StubbedDataSource dataSource = new StubbedDataSource();

   @Given("the basic data set exists")
   public void createBasicDataSet() {
      Assert.assertTrue(dataSource.createBasicDataSet());
   }

   @When("I do the basic work action")
   public void basicWorkAction() {
      Assert.assertTrue(system.performBasicWorkAction());
   }

   @Then("the basic result occurs")
   public void checkResult() {
      Assert.assertTrue(system.isInBasicState());
      Assert.assertTrue(dataSource.isInBasicState());
   }
}

And when we run it, we get green. We’ve essentially done the old “fake until you make it” routine. If we wanted to, we could now move toward swapping in a real data source (perhaps a database?) and real system to test.

Conclusion
The new JBehave is much easier to work with than its predecessor. When it comes to BDD, Java is now a first class citizen.

Enough With The POJOs!

August 17th, 2008

In the last year I’ve heard too much about POJOs. It has died down some, but I still hear it too much. Basically, I am sick of people saying POJO when they mean DTO.

The notion of a framework that works with your existing objects is great. And, if it actually does work with your existing objects, that’s even better.

But, when everything in my system–through ignorance and/or framework–has become a DTO, it kind of pisses me off.

I mean, why is there a setter there? Can the object change state during it’s lifetime? If so, why is there a setter? Why not some other name that doesn’t have to do with implementation? If not, why the hell is it there? Why is that getter there? Do we need to return that value? If so, why? Is somebody asking the object for something rather than telling it what to do? If not, why the hell is it there?

What I’ve heard a lot of is: “Just new up a POJO, and the FlarbleMeister framework will do the rest. It is freaking awesome.” Because of ignorance, framework, and ignorance of the framework, I have to deal with code from the database to the UI with nary a real object. You know, the stuff that can make code easy to work with, the stuff that helps explain the system and allow others (developers working on the code years from now) to intuit what is supposed to happen.

So, please think about it: Is this a real object or a glorified DTO? If it is a DTO, does it belong at this layer in the system? Does it make sense to have it at all? And, please, stop calling it a POJO.