This project is read-only.

Writing your first StoryQ test

Hello StoryQ

This page walks you through the process of creating your first StoryQ test. We've kept the example as simple as possible, so you won't see any realistic tests or assertions going on. However by the end of this page, you will see how you could do this.

Create a new Test project

I've chosen MSTest, but NUnit will do just as well:

CreateAProject.png

Add a reference to StoryQ.dll

You can download this from http://storyq.codeplex.com/Release/ProjectReleases.aspx.

ReferenceStoryQ.png

Write a new story in your test method

In your Test Class (UnitTest1.cs?), first import StoryQ:

using StoryQ;

In your test method, construct a new Story:

[TestMethod]
public void TestMethod1()
{
    new Story("Trying out StoryQ")
}

Flesh out the story with some textual descriptions. Note how StoryQ's fluent interface keeps you on track here, by offering you the right method calls. We use strings for all the narratives that are not executable (everything up to "With Scenario"):

[TestMethod]
public void TestMethod1()
{
    new Story("Trying out StoryQ")
        .InOrderTo("see how StoryQ works")
        .AsA("developer")
        .IWant("to try a simple example")
        .WithScenario("first example")
}

Now that we are up to the "Given/When/Then" stage of the story, we can pass in methods (as delegates) as well as strings. These methods will be run as part of the story's execution:

[TestMethod]
public void TestMethod1()
{
    new Story("Trying out StoryQ")
        .InOrderTo("see how StoryQ works")
        .AsA("developer")
        .IWant("to try a simple example")
        .WithScenario("first example")
        .Given(ThisIsMyFirstTry)
        .When(IRunThisMethod)
        .Then(IWillSeeWhatHappens);
}

This won't compile until you add some method stubs. If you're using a refactoring tool like CodeRush or Resharper, the tool will offer to create the stub for you:

[TestMethod]
public void TestMethod1()
{
    new Story("Trying out StoryQ")
        .InOrderTo("see how StoryQ works")
        .AsA("developer")
        .IWant("to try a simple example")
        .WithScenario("first example")
        .Given(ThisIsMyFirstTry)
        .When(IRunThisMethod)
        .Then(IWillSeeWhatHappens)
}

public void ThisIsMyFirstTry() { throw new NotImplementedException(); }
public void IRunThisMethod() { throw new NotImplementedException(); }
public void IWillSeeWhatHappens() { throw new NotImplementedException(); }

That should compile. What happens when we run the test? At the moment, nothing, because we are missing a very important final step.

Execute the Story

We have to call "Execute" on the fluent interface:

[TestMethod]
public void TestMethod1()
{
    new Story("Trying out StoryQ")
        .InOrderTo("see how StoryQ works")
        .AsA("developer")
        .IWant("to try a simple example")
        .WithScenario("first example")
        .Given(ThisIsMyFirstTry)
        .When(IRunThisMethod)
        .Then(IWillSeeWhatHappens)
        .Execute();
}

public void ThisIsMyFirstTry() { throw new NotImplementedException(); }
public void IRunThisMethod() { throw new NotImplementedException(); }
public void IWillSeeWhatHappens() { throw new NotImplementedException(); }

Running this test should result in a yellow "inconclusive" result (NUnit users will see a "pending" test, also yellow), with the following output:

Story is Trying out StoryQ
  In order to see how StoryQ works
  As a developer
  I want to try a simple example

      With scenario first example
        Given this is my first try   => Pending !!
        When I run this method       => Pending !!
        Then I will see what happens => Pending !!

The test counts as inconclusive or pending because each of the executable lines threw a NotImplementedException. This is the intended first step, because it represents a test that you haven't even finished writing. Most BDD frameworks let you run tests that are not complete. Using pending instead of failing makes it easy to differentiate between a test that's failing and one that isn't yet written.

Notice how StoryQ converts the method name into an english sentence (by un camel-casing it). This feature reduces repetition in your code, because you can just name methods according to what they are meant to do, and human-readable text will be inferred from it. StoryQ will even use parameters that are passed to the method in the description. You can read more about this at method formatting.

Passing, Pending, Failing

Each executable narrative can have one of the following outcomes:
  • Pass: If no exceptions are thrown by the method
  • Pend: If a NotImplementedException is thrown by the method
  • Fail: If the method throws any other exception, such your test framework's assertion exceptions.

Try changing your method stubs to the following to see an example of this:
public void ThisIsMyFirstTry() { }
public void IRunThisMethod() { throw new NotImplementedException(); }
public void IWillSeeWhatHappens() { Assert.Fail(); }

Running this test should result in the following output:

Standard Console Output

C:\Rob\Visual Studio 2008\Projects\HelloStoryQ\TestResults\rfonsec3_WLON1107050899 2010-01-22 12_58_28\Out
Story is Trying out StoryQ
  In order to see how StoryQ works
  As a developer
  I want to try a simple example

      With scenario first example
        Given this is my first try   => Passed
        When I run this method       => Pending !!
        Then I will see what happens => Failed  -> Assert.Fail failed.  [1]

_______________________
Full exception details:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
[1]: Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assert.Fail failed. 
   at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.HandleFail(String assertionName, String message, Object[] parameters)
   at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Fail()
   at HelloStoryQ.UnitTest1.IWillSeeWhatHappens() in C:\HelloStoryQ\HelloStoryQ\UnitTest1.cs:line 83
   at StoryQ.Narrative.Execute()

Note how each failed assertion / exception is assigned an identifier, which corresponds to the list of stack traces at the bottom. This is so that the stack traces do not clutter up the human readable narratives. Also, the first exception to occur is rethrown at the end of the Execute method, which means your test runner will pick up the exception and present it to you (but only if there was a failing narrative):

Error Stack Trace

HelloStoryQ.UnitTest1.IWillSeeWhatHappens() in C:\HelloStoryQ\HelloStoryQ\UnitTest1.cs: line 83
StoryQ.Narrative.Execute()
StoryQ.FragmentBase.Execute(IRenderer[] renderers) 
StoryQ.FragmentBase.ExecuteWithReport() 
HelloStoryQ.UnitTest1.TestMethod1() 

Reporting to a file

If you'd like to see the results of your story execution in a better format than just console output, you can have StoryQ write your results into an xml file. This xml file comes with a default XSLT, which transforms the xml into html. You are welcome to edit the XSLT to suit your needs. This feature is especially useful on a continuous integration server, and what's more it will aggregate all the tests in a run into a single file.

To generate a report file, you need to call ExecuteWithReport instead of Execute. This method can take a MethodBase argument. You are supposed to pass in the current method (easily accessible via MethodBase.GetCurrentMethod()) - StoryQ will use this MethodBase to categorise each story execution:

[TestMethod]
public void TestMethod1()
{
    new Story("Trying out StoryQ")
        .InOrderTo("see how StoryQ works")
        .AsA("developer")
        .IWant("to try a simple example")
        .WithScenario("first example")
        .Given(ThisIsMyFirstTry)
        .When(IRunThisMethod)
        .Then(IWillSeeWhatHappens)
        .ExecuteWithReport();
}

After executing this test, StoryQ will write the report to "CurrentDirectory\StoryQ_Report\StoryQ.xml". If you want know what directory your test runner treats as current, put Console.WriteLine(Environment.CurrentDirectory); at the top of your test and re-run it. You will also see the file "StoryQ-SimpleHtml.xslt", this is what formats your xml as html when you open it in a modern browser. An screenshot example of this report is visible at StoryQ Demo.

StoryQ in the real world

The next step is to take these method stubs and put actual test code into them. A good example of this is provided in retrofitting StoryQ onto existing tests

Last edited Jul 8, 2010 at 1:39 PM by robfe, version 8

Comments

yuipcheng Jan 7, 2013 at 5:09 PM 
When I use the UI tool "StoryQ.Converter.Wpf.exe", my stories seem to be saved somewhere because if I reopen the UI tool, my stories appears and the original template is gone. So my question is that where is my stories saved to?

davidkallen Nov 14, 2012 at 3:18 AM 
Wow! Nice API. Very simple to use, and produces valuable documentation. I love the fluent interface.

robfe Jul 8, 2010 at 1:39 PM 
You are right allan - i've updated the page now. It's removed, but you can get a "simple" report by setting StoryQSettings.SupportsLegacyBrowsers to true.

allan_ravn Jul 8, 2010 at 12:45 PM 
Firstly let me say that StoryQ and BDD seems to be just was I was looking for - Thank you.

It seems like the 'ExecuteWithSimpleReport' is not part of version 2.0.4. Has it been removed or should one just use the 'ExecuteWithReport'? I'm not sure what the difference was but since this example is refering to 'SimpleReport' it could be considered to update the page example.

robfe Jun 24, 2010 at 10:03 PM 
you're right - but these aren't meant to be complete, runnable bits of code at those points. I'll try and make that clearer...

sporcina Jun 23, 2010 at 2:49 PM 
FYI. Some of the code examples are missing semi-colons.