Home | About Us | Stelligent  

TestEarly Weblog

Agile

Code Complexity and Publications and Agile and /Brothers12 May 2008 02:55 pm

I don’t always agree with Mr. Yegge, but this is a great presentation/script on Dynamic Languages with some very interesting ideas and discussion topics.

One point that he never actually got to, but one that I think is worth more discussion - how do you maintain a million-line codebase w/out static types?

My answer is that with a good dynamic language, you have some seriously elegant features and patterns that allow you to keep the size of your codebase small.  Essentially, you don’t maintain a million-line codebase - because it doesn’t take a million lines to write your application.

Which fits in with some of the agile concepts as well - if you are building a project in an agile style, the constant refactoring and removal of technical debt will keep the application smaller and lighter.  The unit tests ensure a clean level of separation of concerns, the DRY and YAGNI principles reduce bloat.

Agile and /Subbarao30 Apr 2008 06:55 am

ThoughtWorks AnthologyThe ThoughtWorks Anthology by ThoughtWorks is a collection of essays which covers a broad range of problems facing IT industry and developers in particular throughout the software development life cycle. You’ll find tons of pragmatic advice to improve the efficiency of your development efforts.

In this book, you’ll find essays on varied topics like refactoring build files, testing for enterprise applications, single click software release and many more.

This book well justifies its addition to the prestigious ranks of Pragmatic Bookshelf. It is well taken and timely, some of the material covered is just mind blowing. This is the real book you need if you are using TDD or planning to, an absolute must-read on the subject.

The book is aimed at several different audiences. The book’s coverage of its subject matter is exhaustive and obviously expert.

Highly Recommended. Stay tuned for a detailed chapter wise review.

/Glover and Business Perspectives and Agile21 Apr 2008 10:14 am

Jim York, a long time Stelligent friend, a Certified Scrum Trainer and lean and agile coach, is conducting a Certified ScrumMaster class May 5-6 in Vienna, VA.

Learn the essentials of working as ScrumMasters, Product Owners, and Scrum team members in this highly-interactive 2-day class. Jim creates an energized learning environment where participants engage in discussion, hands-on simulations, and role play to explore the nuances of Scrum in action. More than an intellectual exercise, Jim challenges attendees to connect Scrum practices to their underlying guiding principles. This class provides what you can’t get from a book — guided experiential learning in realistic scenarios.

Sign up today as space is limited!

Developer Testing and /Glover and Agile02 Apr 2008 07:38 pm

John Ferguson Smart, a long time friend of Stelligent and author of O’Reilly’s “Java Power Tools” will be holding the Java Power Tools bootcamp this May 12th through the 15th in San Francisco, CA. The timing couldn’t be better– it’s right after JavaOne! The course is 4 days of intense hands on workshops covering TDD with JUnit 4, all things Maven 2, CI with Hudson, and much, much more! For more information, visit the course website and sign up today!

Developer Testing and /Glover and Business Perspectives and Agile01 Apr 2008 08:15 pm

The software development process is a big black box for basically everyone on the planet earth, except for a few, proud individuals who speak geek and wear silly tee-shirts. To everyone else who doesn’t read code or wear silly tee-shirts but work with people who do, the last bit of sanity they have is during the time they get to tell development what they want. After that, stakeholders are left praying that at the end of the developmental process, they get something out of it that works. More often than not, if that developmental process takes a long time, stakeholders don’t get want they want.

i am not groovy
Along came iterative processes and customer involvement and things got better. A little. Stuff still broke. And developers still had horrible manners and wore silly tee-shirts. A few of them also appeared not to have learned basic hygiene.

Then came test driven development. Developers’ manners were the same and they still wore silly tee-shirts, but at least the code wasn’t as horrible. Hygienic concerns remained.

Iterative processes became more popular and the stakeholder wanted more. The stakeholder wanted visibility into that black box that those silly tee-shirt wearing developers called the “dev cycle” or the “software construction phrase” but what the normal people called “sit tight and pray a lot” time or “oh gosh, what’s this gonna cost this time?”. After all, they were paying for it and the tee-shirts those developers wore didn’t make any sense (hygienic concerns not withstanding).

Along came the gurus shouting “traceability!” which makes total sense since stakeholders are paying the bill. Emboldened, stakeholders declared:

“When a user selects 3 items, then they should receive a 10% discount.”

Heads nodded. The look of approval was unmistakable. Business was accelerating forward and everyone was happy.

Soon, stakeholders were summoned. The silly tee-shirt wearing developers proudly showed the stakeholders a test case proving the requirement was met and even tested.

assert-equals

The stakehoders looked puzzled. Confused even. And they weren’t trying to read those silly tee-shirts or ponder hygienic skills. Development put their finest heads together and clarified the situation with some documentation:

easyb is easy baby

The stakeholders did their best to understand what they were looking at. In fact, the code even tried to convey more meaning. Yet, no matter how hard they tried, the stakeholders couldn’t speak geek. They couldn’t read the code. They couldn’t laugh at the tee-shirts. They couldn’t not brush their teeth.

Then one of the stakeholders (who used to wear silly tee-shirts) got an interesting idea– why not leverage the same language for both defining the requirements and validating them? In fact, by leveraging BDD constructs and paying attention to what was originally asked for, things can become quite easy.

This is what was originally asked for:

“When a user selects 3 items, then they should receive a 10% discount.”

The key word being should– in fact, the mechanism by which the requirement was requested sounded an awful lot like a story, which could be written like so:

more asserts

Then working with a few developers (who showered that morning), the stakeholder convinced them to author the story using a BDD framework (like easyb), which yielded a file containing the requirements like so:

more asserts

After the code was implemented, the stakeholder was pleased. Other stakeholders were summoned. Other developers were also summoned. Soon heads nodded. Approval was in the air. Business had been accelerated and all involved parties understood each other, for indeed, stakeholders could read what development had finally produced:

more asserts

Stakeholders rejoiced! Developmental jollification ensued. Speaking geek was no longer needed. Things were written in plain English. Those silly tee-shirts still didn’t make sense, but it didn’t matter anymore– stakeholders got what they wanted. They got validation. They got assurance that indeed their requirements had coverage. They didn’t get some of the developers to shower, but they weren’t asking for miracles, just progress. The “sit tight and pray a lot” time became a collaborative effort. BDD had saved the day.

News and Continuous Integration and /Glover and Agile24 Mar 2008 09:22 am

InformIT has published a Q&A with Stelligent’s CTO, Paul Duvall. Paul shares his thoughts on adopting CI, the future of CI, and of course, his thought provoking blog entry. Check it out!

Developer Testing and /Glover and Agile12 Mar 2008 11:23 am

easySince Selenium was introduced a few years back, it has continued to wow developers with how easily a user acceptance test can be knocked out– simply fire up an instance of a Selenium server in the background and then either write a table test or a RC style test– it’s that easy.

RC style testing is particularly powerful as you have full access to programming languages– for instance, with RC, you can write a functional web test in Java by leveraging a framework like JUnit or TestNG. But what’s often lacking with testing frameworks is a more natural way of expressing behavior– or indeed, scenarios and stories.

For instance, a user acceptance test is really a scenario– a user logs into a website, purchases an item, pays, and logs out. That was a sunny day scenario– there are other scenarios that deal with various other paths– user fails to pay, credit card was invalid, etc. All of these scenarios are logically a story– a story about buying something.

Using a standard scenario language, I can more specifically write a scenario (in a story regarding a website for race registrations) like so:

  • given a user is on the race report page
  • when someone enters a first name and last name in the race report form for someone who has signed up for a race
  • then they should receive a list of all races that person has singed up for

That is a happy day scenario isn’t it? One particular negative path would be:

  • given a user is on the race report page
  • when someone enters a first name and last name in the race report form who hasn’t signed up for any races
  • then they should receive a message indicating the person hasn’t signed up for any races

These scenarios can be easily created using easyb, which is a BDD framework for the Java platform– easyb leverages a domain specific language (or DSL) which supports the following syntax for scenarios:

scenario{
 given "", {}
 when "", {}
 then "", {}
}

This DSL is highly flexible– you can chain phrases together with an and phrase and you can have multiple givens or whens or thens if you’d like. Also too, the scenario phrase isn’t required either.

The DSL makes the assumption that scenarios are in files that are either named YourNameStory.groovy or YourName.story– note that YourName is what ever you’d like.

Using easyb then, I can create a story file, which contains two scenarios– my file will be called RaceReport.story and I’ll start by defining two scenarios:

scenario "a valid person has been entered", {}
scenario "an invalid person has been entered", {}

Given that I plan to leverage Selenium, I’ll have to introduce a few new phrases– for instance, a then one that shuts down Selenium.

I’ll start the RC instance in a given phrase like so:

given "selenium is up and running", {
 selenium = new DefaultSelenium("localhost",
  4444, "*firefox", "http://acme.racing.net/greport")
 selenium.start()
}

Note how I’m connecting to a server instance running on the same machine, which will utilize Firefox.

Next, I can chain two when clauses to simulate a user interacting with the report page.

when "filling out the person form with a first and last name", {
 selenium.open("http://acme.racing.net/greport/personracereport.html")
 selenium.type("fname", "Britney")
 selenium.type("lname", "Smith")
}

and

when "the submit link has been clicked", {
 selenium.click("submit")
}

My then clause then verifies that 4 race instances have been returned for my user– note how I’m able to use a nice Groovy for loop that uses a positional index to grab items from a list and from an XPath expression. Not bad, eh?

then "the report should have a list of races for that person", {
 selenium.waitForPageToLoad("5000")
 values = ["Mclean 1/2 Marathon", "Reston 5K", "Herndon 10K", "Leesburg 10K"]
 for(i in 0..<values.size()){
  selenium.getText("//table//tr[${(i+3)}]/td").shouldBeEqualTo values[i]
 }
}

Lastly, I need to shut down selenium:

and

then "selenium should be shutdown", {
 selenium.stop()
}

The entire first scenario looks like this once you put it all together:

scenario "a valid person has been entered", {

 given "selenium is up and running", {
  selenium = new DefaultSelenium("localhost",
   4444, "*firefox", "http://acme.racing.net/greport")
  selenium.start()
 }

 when "filling out the person form with a first and last name", {
  selenium.open("http://acme.racing.net/greport/personracereport.html")
  selenium.type("fname", "Britney")
  selenium.type("lname", "Smith")
 }

 and

 when "the submit link has been clicked", {
  selenium.click("submit")
 }

 then "the report should have a list of races for that person", {
  selenium.waitForPageToLoad("5000")
  values = ["Mclean 1/2 Marathon", "Reston 5K", "Herndon 10K", "Leesburg 10K"]
  for(i in 0..<values.size()){
   selenium.getText("//table//tr[${(i+3)}]/td").shouldBeEqualTo values[i]
  }
 }

 and

 then "selenium should be shutdown", {
  selenium.stop()
 }

}

That’s pretty easy, don’t you think? Of course, my next step is to implement some additional scenarios, such as negative paths with an non-existing runner, etc.

When I run this via the easyb runner, I can get a story printout that looks something like this:

12 behavior steps executed successfully
 scenario a valid person has been entered
  given selenium is up and running on website
  when filling out the person form with a first and last name
  when the submit link has been clicked
  then the report should have a list of races for that person
  then selenium should be shutdown
 scenario an invalid person has been entered
  given selenium is up and running on website
  when filling out the person form with a first and last name
  when the submit link has been clicked
  then the report should have a list of races for that person
  then selenium should be shutdown

The scenarios are slight variations of one another, hence the report looks quite similar — each step is the same, just the data varies.

Functional web stories are a powerful mechanism to verify the proper behavior of web applications from a user’s standpoint. Combining a framework that supports stories and scenarios with Selenium yields an easy way to deliver software more quickly and collaboratively.

Developer Testing and Agile and /Nyika21 Feb 2008 08:30 pm

BDD has been discussed and dissected by many developers and code philosophers since its inception. Thinking about system behaviour is key. Thinking about the manner in which the system will react to external forces in a natural way is core to BDD. Perhaps insight into raw TDD itself will show just how this natural wrapper around TDD emerged.

A system or application emerges (from nothing) incrementally through TDD. What does this really mean? It simply means that a part of a system is constructed by way of the fulfilment of an expectation stated before that part of the system exists. What exactly is this expectation? It is a test (and we know that a test aggresively asserts that something is true about that part of the system, in a nutshell). A test must be satisfied.

//Here's our test subject
public class ZipcodeVerifier(){
   private boolean wasZipValid = false;
   public boolean isZipcodeValid(int zipcode){
       this.wasZipValid = true;
       return this.wasZipValid;
   }
}
//Here's our test
public class ZipcodeValidator{
  @Test
  public void testGoodZipcodeIsIndeedGood(){
     assertTrue(new ZipcodeVerifier().isZipcodeValid(22030));
  }
}

Now, suppose the exercise that just occurred created part of a system (S1). If we step back for a second, we see that S1 was created with a one or more techniques available to TDD (for example Kent Beck gives an example of making a simple test pass, using a technique known as ‘faking it’, where we return the exact type required by the test immediately with no logic attached to determining that value( From his book “Test-Driven Development”)). Let define “faking it”, one of the techniques used, as (tk1).

Also, S1 reacted (S1r) by providing the a value after completing its mission (a boolean). Not all subsystems need to do that (return type void).S1 also changed its internal state from false (S1s1) to true (S1s2). It was not necessary for S1’s own state to change (it may just as well have changed another subsystem’s state, S2, once it, in turn, comes into existence later).

In summary, the simple TDD exercise fulfilled the expectations of a test by creating a subsystem (S1) with a TDD technique (tk1, Beck’s technique) that reacted (S1r) by returning some information (true/false) and changing its internal state (from S1s1 to S1s2).

S1’s change of state calls to mind a style of software architecture: REST (Representational State Transfer). The restful state of the subsystem S1 changed by applying the technique (tk1). Note that some other subsystem, Sn, may have had its state changed too (or instead of S1, or even in addition to S1). The point is, a subsystem’s state is changing when a TDD technique (one or more, tk1…tkn) is applied to it.

But as the number of tests on the same test-subject grows, many more other subsystems will emerge (eg: a refactor may move some code into a private method). Those subsystems may change, in time, the states of other existing subsystems.

The representational state of any one subsystem (Snsn) now seems to become more and more important in determining how another subsystem (Sn+1sm) will react (Sn+1r) OR change the state of yet another subsystem from (Sn+2sy) to (Sn+2sy+1).

Now, if one had to pick any subsystem (Sb) and decide before-hand what one wishes its state to be (Sbsn) (that is, we wish for it to possess a representational state of a specific kind), we have already set an test-expectation for Sb.

Most importantly, however, when we actually specify in (what seems like a natural) descriptive state-representational language about the state of other subsystems that would help give Sb the desired state, we arrive at BDD (or at least the beginings of it). This applies also to the pure inputs to Sb that would cause the needed reaction, Sbr.

For example:
@Test
public void checkThatAddressContainsStateSymbolGivenANonNullZipcode(){}

In effect, we need the subsystem containing what we understand as an Address (for a customer or business) to contain (to possess a state) a State Code (eg: VA or KY) given that another subsystem, the Zipcode Handler, contains a valid state (a non-null zipcode).

Going back to the original example, we can see that there really is no other subsystem that determines S1’s state. We were dealing purely with a reaction (S1r) from the subsystem. If S1 had been re-written as follows:

//Here's our test subject
public class ZipcodeVerifier(){
   private boolean zipValid = false;
   private SimpleDelegator delegator;
   public boolean isZipcodeValid(int zipcode){
       delegator = new SimpleDelegator();
       setZipValid(delegator.determineValidity(zipcode));
       return getZipValid();
   }
  public boolean getZipValid(){
        return this.zipValid;
  }
  public void setZipValid(boolean valid){
        this.zipValid = valid;
   }
}
//Here's our test
public class ZipcodeValidator{
  @Test
  public void testGoodZipcodeIsIndeedGood(){
     assertTrue(new ZipcodeVerifier().isZipcodeValid(22030));
  }
}

Here, we see that S1’s state will change based on another subsystem internal state. The test is really checking that S1 has the state we expect. How? Because of the line:

return getZipValid();
based on the line:
setZipValid(delegator.determineValidity(zipcode));

…So BDD is another way of inquiring whether states and reactions are what they should be from the various subsystems that make up the main system using TDD’s rich toolset of techniques…but more importantly, doing so in simple, descriptive (almost human) terms….

, essentially:


[ BDD = Creating ∑[S1, S2, …, Sn]
injecting fn( { Ss = fn(S1s, S2s, …, Sns ) } and { Sr = fn(S1r, S2r, …, Snr ) } ) using { tk1, tk2, …, tkn } ]

Developer Testing and Continuous Integration and /Owens and Agile14 Feb 2008 04:08 pm

There’s a lot to look forward to if you’re attending the SD West conference in Santa Clara next month. To kick it off, Stelligent’s own, Andrew Glover, will be delivering a half day tutorial introducing Groovy on Tuesday, March 4th. If learning Groovy quickly interests you this is one presentation you can’t miss out on!
Stelligent
On Tuesday evening, I encourage you to attend the “Agile Roundtable” hosted by Stelligent. If you haven’t participated in a Stelligent roundtable previously, this is the one you need to get yourself to. Topics on the discussion table include Test-Driven Development and Continuous Integration. For more information, or to RSVP, please contact mandy.owens@stelligent.com.

Finally, the winners of the industry-acclaimed Jolt Awards will be announced on Wednesday evening, March 5th. We’re quite partial to the “Technical Books” category where we hope Continuous Integration: Improving Software Quality and Reducing Risk jolts the industry!

Developer Testing and /Glover and Agile04 Feb 2008 08:40 pm

Stories offer a powerful mechanism for conveying information– indeed, if written correctly and combined with an adequate means of validation, stories can become executable documentation. For instance, easyb (a behavior driven development framework for the Java platform) supports a story format that consists of:

  • given some condition
  • when something happens
  • then something else should happen (this may or may not necessarily provide validation)

For instance, easyb supports the notion of plug-ins, which are modules that provide additional functionality– currently there is a plug-in that supports database management so that during the context of a story, a database can be seeded. This is, of course, useful should you need to validate high level functionality.

Using easyb itself, it is rather easy to describe what the plug-in does and how to use it. A story to validate the database plug-in sounds a bit like this:

  • given that database has an initalized data model (i.e. tables to hold stuff)
  • and given the plug-in’s method is invoked with a dataset (i.e. rows for tables)
  • when a select statement is issued for a value only found in the dataset inserted by the plug-in
  • then the desired item (i.e. column value) should be returned

In essence, this story is the use case for the plug-in– reading it you can most likely ascertain that the plug-in puts rows in database tables. Reading this story, it is also evident that at some point, it may be helpful to start and stop a database instance during the course of the story– i.e. start it up at the commencement of the story and stop it at the end.

Using easyb’s story format, I can sketch out the body of the story as follows (note, the story includes starting and stopping a database):

given "a database is up and running", {}
and
given "the database has an initalized data model", {}
and
given "the database_model method is invoked with a dataset", {}
when "a select statement is issued for a value that could 
 only be present if the database_model call worked", {}
then "the word bellicose should be returned", {}
and
then "shut down the database", {}

Making the story executable entails adding some logic– in the course of doing so, the story demonstrates how to use the database plug-in (minus the first and last steps, right?)!

The first given can be coded as follows (in Groovy, that is):

given "a database is up and running", {
 Server.main(["-no_system_exit", "true"] as String[])
}

The Server instance in the above code is HSQLDB’s org.hsqldb.Server type. This is, by the way, a handy database that is easily controlled programatically and easy to install (it’s a jar file!).

The next given is a bit more complicated– the database needs an empty schema– one can’t assume one is present, so I’ll just create it. This also happens to validate the story quite nicely– no assumptions are made about the underlying database!

and 

given "the database has an initalized data model", {
 sql = Sql.newInstance("jdbc:hsqldb:hsql://127.0.0.1",
   "sa", "", "org.hsqldb.jdbcDriver")
 ddl = """DROP TABLE definition IF EXISTS;
  DROP TABLE synonym IF EXISTS;
  DROP TABLE word IF EXISTS;

  CREATE TABLE word (
   WORD_ID bigint default '0' NOT NULL,
   PART_OF_SPEECH varchar(100) default ''  NOT NULL,
   SPELLING varchar(100) default '' NOT NULL,
   PRIMARY KEY  (WORD_ID),
   UNIQUE (SPELLING));

  CREATE TABLE definition (
   DEFINITION_ID bigint default '0' NOT NULL,
   DEFINITION varchar(500) NOT NULL,
   WORD_ID bigint default '0' NOT NULL,
   EXAMPLE_SENTENCE varchar(1000),
   FOREIGN KEY (WORD_ID) REFERENCES word(WORD_ID)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
   PRIMARY KEY  (DEFINITION_ID));

  CREATE TABLE synonym (
   SYNONYM_ID bigint default '0' NOT NULL ,
   WORD_ID bigint default '0' NOT NULL ,
   SPELLING varchar(100) default '' NOT NULL ,
   FOREIGN KEY (WORD_ID) REFERENCES word(WORD_ID)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
   PRIMARY KEY  (SYNONYM_ID));
  commit;"""
 sql.execute(ddl);
}

The data model here is quite simple– three tables and I’m using GroovySQL to jam it into the database.

Next, I need to actually use the plug-in to seed the database with data! The core API of the plug-in is the database_model closure, which takes standard JDBC connection information (URL, user name, driver, etc) and a String representing the dataset. In this case, I’m using Groovy’s MarkupBuilder to to create an XML representation of the data (which the underlying code requires– that code uses Java’s own DbUnit, by the way).

and 

given "the database_model method is invoked with a dataset", {
 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()
 }
}

Note, the and clauses– in truth they’re noops but they serve to make the story read more nicely. Notice how the MarkupBuilder instance creates data that matches the data model found in the 2nd given. For instance, the word “bellicose” is inserted with an id of 1.

That right there is the heart of the plug-in– inserting data into the database so that a high level story can play out. Now, using easyb, it’s time to validate that the call to database_model worked.

Validating the database_model call means querying the database for the data that the database_model call should have inserted– in my case, I’ll see if the word bellicose is present!

when "a select statement is issued for a value that could 
 only be present if the database_model call worked", {
  value = null
  sql.eachRow("select word.spelling from word where word.word_id = 1"){
   value = it.spelling
  }
}

Note how I’m still using GroovySQL to talk to the database. Once I have the word (stored in the value variable), it’s time to verify it is there.

then "the word bellicose should be returned", {
 value.shouldBe "bellicose"
}

Note how easyb supports some magic validation via the shouldBe call– easyb supports a few variations, which ever one you pick is up to you– shouldBeEqual or shouldBeEqualTo or shouldEqual all do the same thing.

Lastly, stopping the database is as easy as sending a shutdown command (via SQL) to the instance of HSQLDB.

and 

then "shut down the database", {
 sql.execute("SHUTDOWN")
}

The story behind the plug-in’s behavior doesn’t really require a few documents– it just requires one– the story itself, which as you can see has been implemented in easyb (by way of Groovy, but you can certainly run these in Java). easyb is all about easy– the plug-in was rather easy to describe, don’t you think?

Next Page »