Home | About Us | Stelligent  

TestEarly Weblog

Developer Testing

Developer Testing and /Owens and Tutorial14 May 2008 08:33 am

For any developer looking to test web services, there are a number of tools out there that seem to fit the bill. When you need one that allows you to interact and create functional and load tests with relative ease, soapUI is bound to be the tool you can’t live without.

To help get you started, Meera Subbarao has authored a how-to series on testing web services using soapUI. Published by JavaLobby and entitled, “Functional Web Services Testing Made Easy with SoapUI,” the series is broken up into three installments; with each article demonstrating an important soapUI feature that will make web services development easier for you.

Part 1 explores soapUI basics including how to write functional tests for your web services and how to add assertions to these tests. In short, soapUI emphasizes a good balance between simplicity and rich features and as Subbarao notes in Part 1,

Once soapUI has been downloaded and installed, you can have functional tests up and running in minutes.

For more elaborate programming tasks, Part 2 examines soapUI’s relationship with Groovy. Groovy is used in soapUI primarily for test setup, test teardown, and to decide which steps to start based on the results of the older ones. If you know Java, writing Groovy scripts with the UI will make your testing even easier.

soapUI also includes command-line utilities for running tests and mocks in a continuous integration environment so you’re able to run the test cases you’ve created within it and above all fail the build just like you would when any other unit test fails. Stayed tuned for the third and final part of this series which will cover integrating tests with your build tool, running these tests as part of your builds, and creating JUnit reports.

Developer Testing and /Brothers30 Apr 2008 02:21 pm

We had a proxy problem with Selenium RC today. The site-under-test is behind a proxy, and has the same domain name as the production site (let’s call it shop.mystore.com). Normally, developers set their proxy server in their browser, which then causes requests for shop.mystore.com to go to the proxy server which then sends the request to the developer site-under-test, instead of going to the production site.

We want to set up Selenium so the developers can created automated tests around visiting the site-under-test.

Selenium does have the ability to do a “double proxy”, using system properties (proxyPort elided for length):

java -Dhttp.proxyHost=proxy.server.com -Dhttp.proxyPort=3128 -jar selenium-server.jar

But it turns out, unfortunately, that this doesn’t seem to work in practice. After some investigation of my own, I discovered that the proxy configuration file (proxy.pac) in Selenium is not generated properly.  My own tests, and a timely visit to this discussion of the proxy chaining issue, it appears that there’s a simple workaround:

java -Dhttp.proxyHost=proxy.server.com ... -jar selenium-server.jar -avoidProxy

Setting -avoidProxy causes the proxy configuration (proxy.pac) to work properly, sending the selenium requests to the developer site-under-test.

*Update*

I have discovered there are additional steps that need to occur in some situations, especially when you want to use Chrome and/or SSL. Hopefully this will be fixed in the 1.0 release of Selenium.  Here are the additional steps for using SSL:

  1. Use the  chrome browser
  2. Start the Selenium Server programatically, instead of at the command line.  Yes, that means write code that calls the Selenium server and initializes the proxies, etc before you call the .start() method.
  3. BUT - There’s a bug in 0.92 (and possibly later) that means you can’t set the proxyHost and proxyPort programatically ( ! )

Here’s what you can do. I realize this is complicated.

  1. When you start up firefox or chrome via Selenium, it uses a special temporary profile directory to manage the proxy files and so forth.
  2. Start up Selenium from the command line, with the proxyHost and proxyPort values set.  Then find this profile directory.  Copy it to some other safe, easy-to-remember location.  We’ll call it “/var/tmp/SeleniumProxyHack
  3. Go back to your programmatic launcher for Selenium, and tell it to use /var/tmp/SeleniumProxyHack  as the Firefox Template directory.
  4. From my possibly faulty human recollection - you also need to modify another file in that directory, to tell it to look at the proxy.pac file in /var/tmp/SeleniumProxyHack, instead of wherever it looked before.

Here’s a snippet of code that I use to programatically start Selenium

// these don't work in *chrome in Selenium 0.9.2
System.setProperty("http.proxyHost", "proxy.dev.server.com");
System.setProperty("http.proxyPort", "3128");

seleniumServer = new SeleniumServer(portToUse);
seleniumServer.setProxyInjectionMode(false);
seleniumServer.setAvoidProxy(true);
seleniumServer.setReusingBrowserSessions(true);

String firefoxTemplateLocaton = "/var/tmp/seleniumProxyHack";

SeleniumServer.setFirefoxProfileTemplate(new File(firefoxTemplateLocation)); 
seleniumServer.start();

Yes, I wish there were an easier way as well. And no, I can’t guarantee this will work. But it did work properly for me in a fairly hairy case involving SSL and a fairly well-secured system.

Developer Testing and Continuous Integration and Code Metrics and /Glover18 Apr 2008 09:53 am

Calling all blokes and sheilas– this year’s Asia-Pacific CITCON will be in Melbourne, Australia on June 27th & 28th– registration is now open so claim your spot before space runs out (space is limited to the first 150 tall poppies, surfies, and all around dags)!

If you dream about CI, yabber about TDD, live for BDD, or constantly think about automated deployments, then the Continuous Integration and Testing Conference is a ripper of a time, mates! The conference is free and is run as an OpenSpaces event, so there’s no reason not come. Remember, space is limited so sign up now!

Developer Testing and /Brothers11 Apr 2008 09:48 am

So you want to build a set of automated tests using Selenium against your webapp. I’m going to assume you have already figured out how to launch your app and set the database into a known state.

Now, you want to write some tests that mimic visiting the website and interacting with the UI in various ways.

I’ve been playing with Selenium quite a bit recently, and I’ve assembled a short list of things that will hopefully make other people’s lives easier.

Building your Tests : Navigation

  • Use Selenium IDE (Firefox Plugin) to develop the navigation flow for you. The last thing you want to be doing is debugging your navigation steps in your test case so you can get to the target. With Selenium IDE, you get your app running, and record the clicks and actions you take to get to your destination.
    • When you finish recording, you can export your test as a java program, or in several other languages. Take advantage of this!
  • To click on a link - if you assume you have a link like: < a xhref=" Your Text Here < / a > you can get the Selenium browser object to activate the link by issuing browser.click(”Your Text Here“);

Building your Tests: Validating Results

Selenium has XPath support, and XPath is a very powerful tool for processing HTML. But the syntax of XPath is quite arcane, and I spent waaaaaay too much time trying to decipher what was wrong with my XPath query.

  • Use XPath Checker (firefox plugin) - go to the results page, and control-click to bring up the XPath Checker browser. Then you can experiment with various XPath expressions until you get the one that works for your particular page and content.
  • To find if text appears anywhere on the page (also known as the quick-and-dirty method) - use assertTrue(browser.isTextPresent(”Your Text Here“));
  • To find if text appears in a specific sub-location, the easiest way I have found is:
    • assertEquals(”Text“, browser.getText(”//table[@id=’whatever’]//tr[2]/td[1]”));
    • Selenium is smart about pulling all of the text out of a set of cells, subtags, whatever, so even if that text was nested inside a div, a span and a link, it would still find it.

Running Your Tests

  • You can’t use Selenium inside your tests unless the Selenium RC Server is running - launch it before you start your tests, like you would Cargo, your database, etc.
  • It’s a proxy, so you have to make sure that the port you use in your code (default: 4444) is the same as the port that Selenium server is running on.

Hopefully this will help some future person get up to speed faster.

Developer Testing and Continuous Integration and /Owens08 Apr 2008 10:28 am

Wednesday, April 16th: 3:00pm – 4:00pm ET

Are you seeking to improve the development practices of your organization? Has your team adopted a continuous integration strategy? Are you looking for the best tool to manage your builds? If so, this webinar hosted by Paul Duvall, author of the Jolt award-winning book on Continuous Integration, needs to be penciled into your calendar.

Entitled, “Continuous Integration: Improving Software Quality and Reducing Risk,” the webinar will tackle key topics and practices in the areas of continuous database integration, testing, inspection, deployment and feedback.

If you’re a lead engineer, architect, or development manager striving for greater confidence in your software product, you should tune in to find out more about how CI helps reduce key project risks such as late defect discovery, low-quality software, lack of visibility, and lack of deployable software. Additional topics on the discussion table include:

  • How to use CI leveraging a combination of CI, build, test and inspection tools
  • How to make integration a “non-event” on your software development projects
  • How to reduce the amount of repetitive processes you perform when building your software
  • Effective practices and techniques for using CI with your teams

Registration is required for this event and available at: https://www1.gotomeeting.com/register/656993026?Portal=www.gotomeeting.com

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.

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 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 } ]

WordPress database error: [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1]
SELECT COUNT(DISTINCT ID) FROM