This project is read-only.

t4 template for StoryQ

Jun 3, 2010 at 4:05 PM

Hi, I've created a t4 template for StoryQ

Unfortunately to do that I had to move some classes from the wpf project to the StoryQ project.

Are you interested to see what I've done?

Jun 3, 2010 at 5:22 PM

Of course! I see that you've forked us - this is a great idea. It means that if we don't actually end up pulling your changes into our "trunk", you'll still be kept up to date with our enhancements...

Look forward to seeing your changes pushed in...

Regards - Rob

Jun 3, 2010 at 5:22 PM

P.S. what's the template do?

Jun 3, 2010 at 5:51 PM
on a c# project (I tested it with a web project) Given you have a file called xxx.Q and containing a story in gherkin-style-specification It create a file called xxx.Q.cs with a partial class with your story in c# And it create a file calles Test.Qmethods.cs with partial class with a default implementation of your handlers. So the only thing you have to do is to implement the methods in Test.Qmethods.cs When you update the xxx.Q file, xxx.Q.cs is automatically updated so if you change a story you'll have a compilation error if you do not implement all your new methods. the 3rd file is generated once and never modified Test.Q ---------------------------- Story is a Test In order to show how the t4 works As an agent I want to create a test And I want to verify the agent permissions With Scenario Sum 2 numbers Given I have a number $12 And I have a number $2 When I sum the numbers Then the result is $14 ---------------------------- Test.Q.cs ---------------------------- namespace {the namespace comes from the location of the Test.Q file} { using System; using StoryQ; using MbUnit.Framework; [TestFixture] public partial class ATestTest//the name of the class comes from the .Q file { [Test] public void ATest() { new Story("a Test") .InOrderTo("show how the t4 works") .AsA("n agent") .IWant("to create a test") .And("I want to verify the agent permissions") .WithScenario("Sum 2 numbers") .Given(IHaveANumber_, 12) .And(IHaveANumber_, 2) .When(ISumTheNumbers) .Then(TheResultIs_, 14) .Execute(); } partial void IHaveANumber_(int arg1); partial void ISumTheNumbers(); partial void TheResultIs_(int arg1); } } ---------------------------- Test.Qmethods.cs ---------------------------- namespace {the namespace comes from the location of the Test.Q file} { using System; using StoryQ; using MbUnit.Framework; public partial class ATestTest { partial void IHaveANumber_(int arg1) { throw new NotImplementedException(); } partial void ISumTheNumbers() { throw new NotImplementedException(); } partial void TheResultIs_(int arg1) { throw new NotImplementedException(); } } }
Jun 3, 2010 at 5:52 PM
ups, a bit of a mess with the code I'll soon commit my version with a web project with a t4 template to show what it does Best
Jun 4, 2010 at 1:01 AM

you can pull my fork, open StoryQ.T4 project, update Test.Q story and run the t4 template, or create a new Q file and run the custom template.

Jun 4, 2010 at 5:24 PM

Hey - that's pretty cool. I'm really impressed by what you've done - but there's a few reasons why i've never commited anything similar myself:

  1. The StoryQ converter isn't perfect, you often want to fiddle with what it generates
  2. Specflow already does a really really good job of generating unit tests from plain text (*.feature) files - it even lets you add breakpoints!
  3. (most important) by treating plain text as your source of truth (rather than how StoryQ and MSpec treat code as the source of truth), you lose some refactorability / manageability. This advantage only becomes apparent as your project matures.

I'd encourage you to try out a workflow where you generate tests with the StoryQ converter, but only check in / keep StoryQ test class code. You can typically paste the output of StoryQ back into the converter if you ever want to "keep" the plain text. In the long run, it's made the most sense for most of my projects. If you really do want to have plain text files checked in with your project - then I think SpecFlow is probably always going to be a better tool - T4 will never be as powerful as a VS plugin...

That really was a cool template though :(

Jun 5, 2010 at 11:25 AM

I'm a contributor for Specflow myself, where I work we are trying to analyse both the framework to see which one does the best job.

I think treating the code as your source of truth is not the right choice since in the ideal world, it's the business that write the scenarios, so it's much easier for them to write in in English than in c# and the scenario is always part of the documentation and always in sync with the code.

I think the t4 template is a good compromise, since it's not mandatory, but you use it only if you want.
Anyway, to make it work, some changes needs to be applied to the code converter. (classes needs to be moved to the core and made pubblic)

Another thing you should think about, is, for example, when you have a story with multiple scenarios, your converter transform everything in a single class, with a single method with both the scenarios implemented.
In this way, if I import that generated code into my test class, I have only one method that test 2 scenarios. I think  Specflow does the correct thing generating 2 methods, so you have 2 separated test for the 2 scenarios.

I wrote the t4 plugin because I saw some blogs asking about it, so may be we can polish the code a little bit and publish it anyway, and see if that is the right direction to go.

BTW I'm fighting with my colleague that thinks code is the way to go, while I think plain text is the way to go, so it's an open debate :)

Jun 7, 2010 at 9:10 AM

The advantage of having plain text specifications checked in is that non-developers can edit the files.

The advantage of having code-based specifications checked in (like StoryQ or MSpec) is that it's easier to debug, refactor and understand. 

In our workflows, we've had developers and business analysts / users sitting down together, writing text into the converter. The developer then quickly pastes in the code, & runs it to show the pending test to the user. Later on, the user will copy scenarios out of the CI server report, and modify the plain text, and email that to a developer. It's a cinch for the dev to include this in the test base. We feel that it's the output of the BDD process that needs to human-readable, and the input is something that needs to be refactorable and manageable. Business analysts / users don't think about step re-use, so to prevent your test suite from becoming unmaintainable, you need to get developers involved in the input of them too. This was the pain we felt with FitNesse, which was why we built StoryQ in the first place.

The other thing I don't like about the t4 template "compromise" is that it takes away some of StoryQ's simplicity. This is one of the biggest selling points we've got. That said, I think your fork is a cool idea and i'm happy to help you maintain it if you do end up using it - but i'm not convinced that i'll want to pull it...

I'll definitely look into the method-per-scenario generation...

Cheers - Rob


P.S. listen to your colleague ;)

Jun 26, 2010 at 4:29 AM

+1 for method-per-scenario...

Rob, just getting familiar with StoryQ, and we're loving it! But (admittedly with limited experience so far) it seems we could also benefit from having a separate test for each scenario. I know you've said elsewhere that you think of scenarios as sequential, but do you have any examples you can point me to? All your samples I've found have only one scenario per story. Once we get into more complex stories, we're finding we can always think of multiple "scenarios". And they don't generally follow one from the other -- we're imagining parallel paths through the same feature. Obviously the steps within a scenario are sequential, but to me the whole point of starting a new scenario is to start over. If I wanted to continue where I left off I'd just keep adding steps to the original scenario. The way we're using scenarios, we need setup/teardown before/after every scenario to reset the repository state. I realize there are other ways to do this (by creating a new story for each scenario) but it's harder to make this DRY, and doesn't seem as intuitive to me, given my pre-existing understanding of the term "scenario".

Jul 2, 2010 at 7:36 AM
Jeremy, sorry i've taken so long to reply - i lost your question! I've just committed a demo that reuses a story. Hopefully this demonstrates how steps can be reused. Note that the story is declared as a Feature, this is because a Feature is what IWant returns. You could, if you wanted, put a couple of scenarios in some of these test methods.
Jul 2, 2010 at 7:52 AM
... And I've documented it here: