Home | About Us | Stelligent  

TestEarly Weblog

November 2007


Continuous Integration and /Owens and Tutorial30 Nov 2007 11:43 am

On the IBM developerWorks site, there’s a new tutorial demonstrating how to set up a Continuous Integration process. Authored by Andrew Glover, “Spot defects early with Continuous Integration” lays out a complete step-by-step guide to creating a best-of-breed CI environment using Hudson, Ant and Subversion. The resulting build process will run both tests and software inspections and will report back violations almost as quickly as they occur.

Thanks to the tutorial you’ll soon discover that Hudson is very easy to setup and get going. What’s more, even though the tutorial assumes Ant and Subversion as the build tool and repository, you’ll see that you can easily plug in Gant or Maven, CVS or ClearCase, etc.

For more articles addressing best practices for ensuring your code is the best it can be, check out the acclaimed “In pursuit of code quality” series or the accompanying discussion forum for assistance with code metrics, test frameworks, and the creation of quality-focused code.

Developer Testing and News and /Glover21 Nov 2007 12:17 pm

SDTConf 2007 is rapidly approaching and will be held at Penn State on November 30th through December 2nd. This is a free conference and much like CITCON, is also run as an open spaces event. With guys like PJ, Brian Marick, and Ron Jeffries attending, this should be an excellent weekend! Plus, Stelligent is also a sponsor so sign up today!

Developer Testing and News and Build Management and /Owens13 Nov 2007 08:42 am

Over the course of a few years a number of build automation tools have surfaced. One tool that is widely accepted as a standard in the Java community is Ant, a cross-platform build tool that uses an XML file format.

Ant’s attractiveness stems from its ease-of-use and ability to be seamlessly extended with custom capabilities. Plenty of people know how to use Ant and there is a broad ecosystem of tools and support around it. On the other hand, given the nature of the XML syntax, Ant is occasionally limited when it comes to expressiveness. As a result, build tools based on an existing scripting language have entered the scene.

One such tool, Raven, a build platform built on top of Ruby, leverages the power of a full-featured programming language with the simplicity of a build-centric Domain Specific Language. Paul Duvall describes this in the latest installment of his “Automation for the people” series,

“In particular, Raven enables dependency-based tasking with a full-featured imperative programming language (rather than a declarative one like XML).”

In addition to expanding on the benefits of Raven including demonstrating two approaches to getting Raven installed and configured, his article, “Build Java projects with Raven” also illustrates the relationship between Raven and Rake. If you’re looking for a tool that enables you to utilize the power and flexibility of the Ruby language within a build script, check out the article first, then check out Raven.

Learn about the other installments of “Automation for the people”, a series of articles dedicated to exploring the practical uses of automating software development processes and teaching you when and how to apply automation successfully.

Developer Testing and /Glover and Agile11 Nov 2007 08:44 am

Behavior Driven Development, or BDD, elegantly shifts ones focus from tests to behavior and in doing so, opens up a whole new set of possibilities when it comes to collaboration and indeed, verification. In fact, by focusing on behavior (in terms of thinking about what something should do and how one could ensure things happened as planned), I’ve found that BDD effectively drives development in a rapid manner– what’s more, through the notion of stories, BDD can bridge the stakeholder-developer gap that often exists. As such, behaviors turn out to be phenomenal documentation– documentation that is living and can be executed often.

Having seen the light with RSpec and indeed, rbehave, I found myself wanting the same simple expressiveness in Java– accordingly, I began experimenting with Groovy and internal DSLs (with the help of some friends) and came up with something I find quite simple and expressive.

The first incarnation of behaviors has a simple feel and attempts to read in plain English in an effort to have stakeholders participate. In fact, the simple language is like so:

before "some description", {
//do fixture like logic
}
it "should do something...", {
}
//as many its as you'd like

For instance, taking the same behavior I coded in an earlier post, I now have:

before "initialize zipcodevalidator instance", {
 zipvalidate = new ZipCodeValidator()
}

it "should deny invalid zip codes", {
 ["221o1", "2210", "22010-121o"].each{ zip ->
  ensureThat(zipvalidate.validate(zip), eq(false))
 }
}

it "should accept valid zip codes", {
 ["22101", "22100", "22010-1210"].each{ zip ->
  ensureThat(zipvalidate.validate(zip), eq(true))
 }
}

As I tried to incorporate this first incarnation into an existing legacy project, I found that I needed a higher level story line– for instance, I wanted to ensure the behavior of a DAO style object worked accordingly; however, in order to do so, I needed a seeded database and a Spring initialized context.

As a result, I began to realize that the simple before-it style of behaviors wasn’t enough– indeed, following JBehave’s story style of development, I ended up adopting a given-when-then language. For instance, a simple story (or scenario, really) looks like this:

given "some needed precondition", {

}
when "something occurs", {

}
then "ensure that something else is true, etc", {

}

This DSL supports multiple givens, whens, and thens as well– the given closure delegates to an object that can handle database seeding via DbUnit as well.

For instance, if you need to put a database into a known state before a story, you can do any one of three options, using the database_model call:

given "the database is properly seeded", {
  database_model("org.hsqldb.jdbcDriver",
   "jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
    def writer = new StringWriter();
    def builder = new MarkupBuilder(writer);

    builder.dataset(){
     word(word_id:1, spelling:"bellicose", part_of_speech:"Adjective")
     definition(definition_id:10, definition:"demonstrating willingness and willingness to fight",
      word_id:1, example_sentence:"The pugnacious youth had no friends left to pick on." )
     synonym(synonym_id:20, word_id:1, spelling:"belligerent")
     synonym(synonym_id:21, word_id:1, spelling:"aggressive")
	}
  return writer.toString()
 }
}

In the above code, a MarkupBuilder is used to create an XML representation of the data desired in a database– note that the closure returns a String– this is key as it means there are multiple ways to return XML to the delegate, which ultimately uses DbUnit’s native data types to seed the database.

given "the database is properly seeded", {
  database_model("org.hsqldb.jdbcDriver",
   "jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
   """<?xml version='1.0' encoding='UTF-8'?>
   <dataset>
    <word WORD_ID="1" SPELLING="pugnacious" PART_OF_SPEECH="Adjective"/>
    <definition DEFINITION_ID="10" DEFINITION="Combative in nature; belligerent."
      WORD_ID="1"
      EXAMPLE_SENTENCE="The pugnacious youth had no friends left to pick on."/>
    <synonym SYNONYM_ID="20" WORD_ID="1" SPELLING="belligerent"/>
    <synonym SYNONYM_ID="21" WORD_ID="1" SPELLING="aggressive"/>
   </dataset>
   """
  }
}

In the code above, a String representation of the XML is returned as is– this is probably the least desired mechanism to do this; however, it works.

Lastly, the delegate can be fed a String representation of an existing DbUnit XML document from the file system as follows:

given "the database is properly seeded", {
  database_model("org.hsqldb.jdbcDriver",
   "jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
	 return new File("./src/conf/seed.xml").text
  }
}

Putting it all together yields stories that are readable by stakeholders and are quite effective as documentation– executable documentation:

import org.springframework.context.support.ClassPathXmlApplicationContext

given "the database is properly seeded", {
 database_model("org.hsqldb.jdbcDriver",
  "jdbc:hsqldb:hsql://127.0.0.1", "sa", ""){
    return new File("./src/conf/seed.xml").text
 }
}

given "the DAO instance has been obtained from Spring", {
 context =
  new ClassPathXmlApplicationContext("spring-config.xml")
 dao = context.getBean("widgetDAO")
}

when "findWidget is called with a valid id", {
 wdgt = dao.findWidget("34-02w")
}

then "a working Widget object should be returned", {
 ensureThat(wdgt, isNotNull())
 ensureThat(wdgt.getLineItems().size(), eq(2))
}

Running this story is as easy as invoking the Ant task- for instance, in Gant, the task looks like so:

Ant.specrunner(){
 report(location:"${defaultdir}/task-report.xml")
 behaviors(){
  fileset(dir:gbehaviordir){
   include(name:"**/*Story.groovy")
   include(name:"**/*Specification.groovy")
  }
 }
}	

As you can imagine, using normal Ant is similar (except with a lot of XML)–

<specificationrunner>
 <report location="${loc}/report.xml"/>
 <behaviors>
  <fileset dir="${loc}" include="**/*.groovy"/>
 <behaviors>
<specificationrunner>

The story and behavior framework is built upon JBehave, so anything you can do in JBehave, you can do in various closures– notice the ensureThat methods– all matchers are available as well.

Executable documentation is a sure fire way to:

  • accelerate delivery
  • quantify development

It bridges stakeholders and development and effectively builds confidence that development is building the right thing. Using a DSL, like the one above, makes this process easier as well.

Developer Testing and Continuous Integration and /Owens09 Nov 2007 02:43 pm

CI experts, Jeffrey Fredrick and Andrew Glover will be hosting a free webinar on how to implement continuous integration and testing this Wednesday, November 14th- 12:00 pm (EST) / 9:00 am (PST).

Fredrick is the lead committer for CruiseControl, the defacto standard CI tool, while Glover most recently co-authored the book Continuous Integration: Improving Software Quality and Reducing Risk.

These guys obviously know their stuff. If you’re interested in learning more about CI and how you can start taking advantage of it today, please register now!

Developer Testing and News and /Owens and Agile08 Nov 2007 05:07 pm

In our first, “Share your TDD horror stories” event last Tuesday, October 30th, the turnout was quite “spooktacular”. It was the Stelligent staff who came dressed in costumes for the occasion, but it was the non-dressed in attendance that put on a good show in conversation around TDD scares.




One theme that was hammered throughout the night was that expertise in TDD begins to materialize at the point where the developer realizes that it’s not about testing, but about defining behavior.

Another observation I found interesting was that TDD design work encourages the reduction of cyclomatic complexity (CC); ultimately making test fixtures more readable and maintainable….and as Andrew Glover noted earlier this year:

Projects that carry out TDD will find their code bases are rarely flagged for high cyclomatic complexity values.

You’ll want to check out the results from a survey we handed out– I wasn’t surprised to find out that 84% in attendance said that their organization does NOT actively practice TDD. The most likely culprit in the adoption rate is the general resistance to change; those who prefer the comfort of the tried and tested. To help pacify this opposition, basic education is key before most will be able to initiate/succeed with it.

Many thanks to everyone for coming and a special thanks to Savoy-Lee for the terrorific selection of fine wines.

/Duvall and Business Perspectives08 Nov 2007 03:50 am

We received over 80,000 unique hits to my blog post, “Fire your ‘best’ people, reward the ‘lazy’ ones”. Based on comments here and postings on other sites, it’s fair to say that many of you seem to agree that if you have too many people on a project that focus exclusively on troubleshooting, you’ve got a problem. I figured this post deserved further explanation…

Milton

I wrote this based on my experiences in working on dozens of projects as either a developer, tester, PM, architect or consultant. Some of the behavior that teams are rewarding will not lead to getting better software out the door faster. There’s no way you can prevent every problem from occurring on a project. However, when problems do occur, it’s important to ask two questions:

Why did this happen?”

-and -

“What are we going to do to prevent it from happening again?”

That’s it. People need to troubleshoot issues, but they must also be asking these questions after fixing the problem. In the post, I pit the troubleshooter against the troublepreventer, but I go on to say that, without question, you need troubleshooters on your project. I am poking at the people that focus so much on troubleshooting that they forget to look to prevent the problem from occurring in the first place. The time you invest in fixing or preventing a problem should be based on risk. It’s probably not worth investing several days on preventing a problem from occurring if the likelihood of its occurrence is low and the impact of the realizing the risk is minimal. However, it may be worth your time if the likelihood is low/medium and the impact is high/severe (e.g. application will not work). Obviously, if it’s already happened, the likelihood is rather high, don’t you think?

Even today, there are many that firmly believe that if a team works to improve/introduce software quality, it will delay the schedule. The antithesis is a false economy . In my experience, effectively employing practices/techniques such as developer testing, creating a fully automated build, continuous integration (CI), and automated deployment speed up quality and delivery with teams. Of course, I used a trick (some may say ‘clever’) word in the previous sentence…”effectively”. For instance, if you try to do CI without a fully automated build, you will have problems. Or, try to write developer tests that rely on specific values in the database that aren’t aren’t updated/integrated into scripts, you’ll have problems. There’s no silver bullet here.

People will ask, so “If I do TDD, CI and automated builds, will this improve my speed and quality of delivery?” I must, in all good conscience, give you the consultant’s answer: “It depends!” If you’re incorrectly implementing these practices, it doesn’t matter what you call it, they’re not going to magically solve problems just because you gave it a name. Unfortunately, the practices themselves can be misappropriated as the culprit of the schedule delay or quality problems (e.g. I always get a chuckle out of the: “We stopped using CI because our builds kept failing”).

Fail fast is a good mantra to follow. Learn from your mistakes and improve. Reacting to the latest emergency is necessary and inevitable. However, teams should seek to always learn and improve to lessen these occurrences in the future. People may say “Well, that’s just obvious!” Then, I will leave you with one of my favorite blog posts from Kathy Sierra. There’s a difference between saying and doing .

/Gurses and Agile06 Nov 2007 11:29 pm

It’s popular to coin new phrases these days, so here is one from truly yours. The lowest common denominator agility signifies the total agility of an enterprise and it means your enterprise is only as agile as its least agile unit.

Although highly effective agile teams, often supported by maverick managers, have delivered significant results in specific areas of efficiency and flexibility, it remains a fact that a business can be only as agile as the IT systems that support it.

Without looking into enterprise agility, small software teams often fail to impact the overall enterprise agility by concentrating on a narrow deliverable or a small module of the overall enterprise. Current agile literature promotes small teams, which is understandable. A small team is manageable and can deliver real results really quickly. What’s missing is uber-project management with the Enterprise in mind.

Lately, successes in Service-Oriented Architecture (SOA) have enabled business agility by bringing structured approach to model, assemble, deploy and manage key services in the enterprise. It’s probably the “architecture” in SOA which makes some in the industry confuse SOA for technical features or geek-sensation. Some even suggest that it’s nothing but the good old web services repackaged in glossy paper. I disagree. SOA is a largely business term and its designed to enable enterprise agility by making the business decision makers realize what technical folks have been harnessing for years: reuse, transparency, interface decoupling, flexibility.

SOA has the potential to make disperate business units and IT functions work better together; reuse and consolidate software and maintenance and generally make changing services easier and faster and thus it can increase the lowest common denominator agility of your enterprise.

Next time: What is Agile SOA?

Developer Testing and /Julius06 Nov 2007 09:26 am

In a lot of ways, developer-time testing is a solved problem. Not to say that test-driven development is always easy. There are still plenty of people and technical issues to sort through when you decide to start testing your application aggressively. That said, I think that bringing testing into every aspect of your software development lifecycle presents a much greater challenge, and therefore fun to tackle.

I get asked frequently how to automate testing for every team member. The reasoning usually goes something like this, “If test-driven development is good for programmers, why wouldn’t it be good for business analysts?” Feel free to replace “business analysts” with anyone on the project team - customer, project manager, quality assurance engineer, etc. It may seem a little radical. Fortunately, I agree with them in principle.

In fact, I like to say that tests are the primary artifacts that drive the communication from one team member to another. More precisely, I mean an executable test that gets run with every build and fails when the application no longer does what we want. In this post, I describe how my team and I got this working on a very successful project.

I’ll set the stage by describing the application, team makeup and development process. The application was a “back-end” system, meaning that it had no graphical user interface. Messages flowed into the system, which in turn updated the state of the database and orchestrated various interactions with other external systems. After much processing, the application spit out a message to indicate success, failure or some variation of the two. The entire project ran fulltime for a little more than one year. The team consisted of about 15 people consistently, sometimes going as high as 25. We had a fantastic war room, large enough for everyone on the team. And, we had a very well defined workflow for our Stories. At each step in this process, there was a heavy focus on testing.

story process small

Yep, that’s right, two passes through Quality Assurance. I’ll come back to why. And, just in case you think this sounds a little heavyweight, a Story would flow through this process in less than 2 weeks with lots of opportunity for the all-important feedback loop. We usually had about 6 Stories flowing in parallel to keep everyone on the team fully utilized.

Step one was prioritization with the customer. As the business customers reviewed and prioritized Stories, they would conduct meetings to determine what each Story really meant. Inevitably during this meeting interesting edge cases would arise. If the edge case was in scope for the Story, it would be documented in the body of the Story card. Those edge cases were the first stab at testing. Each case was essentially a comment from the customers saying “…and don’t forget to test that the application will handle this scenario”. Over time, the customers learned that by documenting these interesting variations right alongside the Story, they were helping to make the application better.

Next, the Story would get a thorough analysis. That meant looking into the guts of the functionality to make sure that every aspect was written down for the developer. As a part of that, the analysts would create tables of test scenarios. In fact some Stories consisted mostly of test cases. It’s surprising how well one can communicate complex functionality by giving examples. The amount of verbiage in the Story decreased as the analysts started to think more about how to test the functionality, instead of how to describe the functionality.

The analysts would also incorporate those edge cases identified by the business customers into the test cases. Frequently, the analysts would realize even more unique variants, and those too…would be documented in the Story as an example test case.

Ok, so far, this doesn’t sound much different than what everyone does. The difference was, those tables of test cases identified by the analysts were executable! Ok…you caught me…they were nearly executable. We taught the analysts how to create test cases consumable by the testing framework Fit, and FitNesse. The output from the analysis process was a textual description of the desired functionality with embedded executable (nearly) example test cases.

The third step in the process was a stop by the quality assurance folks. They would review the Story and think about how to test the functionality. They frequently discovered even more variations and potential impact to the rest of the system functionality. They possessed an intimate understanding of the custom FitNesse fixtures defined by the team. Therefore, they were able to streamline the testing, by using meaningful variables, random number generators to increase the test’s completeness, etc.

At this point, the Story was truly executable. Meaning, we could run it in FitNesse. It would of course fail, because the functionality hadn’t been implemented by the development team, but we would get a red bar. Red bars make a good starting point for writing code.

And here we are! Developers get to write some code to make that test pass.

We referred to our development approach as “Fit-First Development”. Just like test-driven development, where you start by writing a broken unit test, we would start with a broken Fit test and write just enough code to make it pass. Actually, we would drill down from the Fit test into the code, writing tests all the way along. We would sometimes expand the Fit test. We would always write unit tests, in this case using JUnit. As we got the unit tests passing we would pop our way back up to the Fit test. Sometimes, we would get the Fit test working one table row at a time until the correct functional implementation emerged.

As the tech lead on the team that pair programmed to write code all day long, I found the approach to be exhilarating. Never before had I felt so assured that the code my pair and I wrote actually did what the business wanted.

After the developers completed the code, i.e. made the Fit test green bar, they would pass it back to the QA team. One point here…The QA team was sitting in the same room. As mentioned, everyone including the customer was sitting in the same war room. Although my description might make it sound like chunks of work were being lobbed over the wall, that wasn’t the case. We talked back and forth continuously. There were times when the developers would encounter a contradiction between the plain English description and the test scenarios. In those cases, it was a matter of minutes before the analysts and QA people were hunched over the developer work station determining the correct answer.

So, the Story, along with the code flowed back into the hands of the QA team. They would do a thorough review of the functionality. Sometimes they would add more test scenarios that had become obvious, which might in turn result in the Story heading back into development (the aforementioned feedback loop). Once QA was satisfied, they would call the customer representative over to do a final functionality walk-through. Since it was a back-end system, the Fit test plan provided a visual mechanism that even a technically challenged person could relate to. When the customer representative was satisfied, the final sign-off was provided. In this manner, each and every Story went from start to finish.

A side-effect of this approach was that a huge regression test suite was created step-by-step throughout the course of the project. The executable Stories were stored in Subversion, right alongside the code. The Stories, and the tests contained therein, became first-class artifacts that warranted ongoing maintenance to ensure that functionality developed months ago didn’t inadvertently get broken.

The other aspect of this was that we included the entire FitNesse wiki in Subversion, too. We used lightweight, in-memory containers to simulate the production environment. That meant that anyone on the team could checkout the project from Subversion and run the entire regression test suite, locally. Nobody had to connect to a central server. Nobody needed their own database schema. You could checkout from Subversion, double-click a batch/shell script, and off you go. Everything just worked!

Was it easy to make everything just work? Yes. It was easy because we started the project knowing that we wanted to make everything just work. It was the culmination of a couple years of trying to get better and better about automating the entire process. But now, I would seldom knowingly do it any other way. Automate everything. Check in everything. Make your Stories an executable description. And treat those Test Scenarios just like you would your application’s code.