Skip to content

Unit or Functional(*), That is the Question

Another lunchtime discussion…”So. is easyb for unit testing or functional testing? Which is it?”

Does it have to be either? It is a testing tool that is driven by stories. These stories can be helping us to understand either how our units of code operate or what constitutes an acceptably-behaving system.

Since easyb is a Groovy DSL and since Groovy interoperates fully with Java, it is easy to incorporate a tool such as Canoo Webtest. For example:

description "Testing a Web Application"

narrative 'Can we test a web application in a scenario? Yes. Yes we can!', {
  as_a "Starving Developer"
  i_want "To test my web application"
  so_that "I can get a better job elsewhere"
}

ant = new AntBuilder()

webtest_home = 'C:/DEVTOOLS/Canoo WebTest 2.6'

ant.taskdef(resource:'webtest.taskdef') {
  classpath() {
    pathelement(location:"$webtest_home/lib")
    fileset(dir:"$webtest_home/lib", includes:"**/*.jar")
    }
}

scenario "The Transentia Web Site Is Up and Running", {
  given "The URL for the Transentia Web Site"
  when "We look for the page subtitle"
  then "We must see the appropriate byline", {

  ant.testSpec(name:'groovy: Test Groovy Scripting at creation time'){
    config([host:"www.transentia.com.au", basepath:'flatpress'])
    steps() {
      invoke(url:'index.php')
      verifyXPath(xpath: "//p[@class='subtitle']", regex: true, text: '.*training.*')
      }
    }
  }
}

It’s good to look at this example and see the synergies Groovy brings to the task: would a ‘pure’ Java developer normally reuse ant as shown above?

A similar use of easyb is given in Functional web stories, but that example uses selenium, not WebTest. There is also a useful followup article covering the use of easyb fixtures to improve the script at http://thediscoblog. … ixtures-easyb-style/.

I like the idea of a single tool being able to drive various testing activities, I particularly like the way that this gives a consistent ‘feel’ to the reporting:

 1 scenario executed successfully

  Story: transentia story
   Description: Testing a Web Application
   Narrative: Can we test a web application in a scenario? Yes. Yes we can!
      As a Starving Developer
      I want To test my web application
      So that I can get a better job elsewhere

    scenario The Transentia Web Site Is Up and Running
      given The URL for the Transentia Web Site
      when We look for the page subtitle
      then We must see the appropriate byline

(as an aside, this consistency of reporting style can also be achieved by getting easyb to output an XML report that can then be transformed in any which way…)

So my answer to the question is “easyb can be used in any way that makes sense, but consider the value of a consistent documentation stream.”

Now, just to be complete and to show that I do “eat my own dogfood”, here is the associated gant script:

DEVTOOLS = 'c:/DEVTOOLS'
dirEasybHome = "${DEVTOOLS}/easyb-0.9"
dirWebtestHome = "${DEVTOOLS}/Canoo WebTest 2.6"
dirReport = 'reports'
includeTargets << gant.targets.Clean
cleanPattern << '**/*~'
cleanDirectory << [ dirReport ]

dirGantHome = ant.project.properties."environment.GANT_HOME"
ant.path(id: 'pathGant') {
   fileset(dir: dirGantHome, includes: 'lib/*.jar')
}

ant.path(id: 'pathWebtest') {
   fileset(dir: dirWebtestHome, includes: 'lib/*.jar')
}
ant.path(id: 'pathEasyb') {
   fileset(dir: dirEasybHome, includes: '*.jar')
}

ant.taskdef(name: "easyb", classname: "org.disco.easyb.ant.BehaviorRunnerTask", classpathref: 'pathEasyb')

target(easyb: 'Run easyb tests') {
  depends(init)
  ant.easyb(failureProperty: "property.easyb.failed") {
    classpath() {
      path(refid: 'pathEasyb')
      path(refid: 'pathWebtest')
      path(refid: 'pathGant')
    }

    report(location: "${dirReport}/xml-report.xml", format: "xml")
    report(location: "${dirReport}/story-report.txt", format: "txtstory")
    report(location: "${dirReport}/behavior-report.xml", format: "txtspecification")

    behaviors(dir: '.') {
      include(name: "**/*.story")
    }
  }
  ant.fail(if: "property.easyb.failed", message: "***easyb run failed")
}

target(init: 'Initialise the build, given a clean start') {
  depends(clean)

  ant.mkdir(dir: dirReport)
}

setDefaultTarget(easyb)

This should reinforce the message from Goodybye Ant, Hello Gant.

(*)Just to say, I dislike the term “functional testing”, I much prefer acceptance testing.

Tags:

Java Enterprise Edition, JEE, JavaServer Pages, JSP, Tag Libraries, Servlets, Enterprise Java Beans, EJB, Java Messaging Service JMS, BEA Weblogic, JBoss, Application Servers, Spring Framework, Groovy, Grails, Griffon, Seam, Open Source, Service Oriented Architectures, SOA, Java 2 Standard Edition, J2SE