Navigation Menu

Skip to content
richardlawrence edited this page Nov 7, 2011 · 20 revisions

Cuke4Nuke

Cuke4Nuke is no longer under active development. Check out SpecFlow for a current .NET version of Cucumber.

Cuke4Nuke is a project to allow Cucumber to support step definitions written in .NET. It uses a simple wire protocol for Cucumber to issue commands to a .NET server that knows how to read and invoke .NET step definitions.

The goal: to make Cucumber usable for .NET teams who can’t or don’t want to work directly with Ruby.

Quick Introduction

If you’re in a hurry, grab a coffee and watch this excellent introductory screencast by the creator of Cuke4Nuke, Richard Lawrence.

Why “Cuke4Nuke”?

The native Java step definition support for Cucumber is called Cuke4Duke, after the Java mascot, Duke. When we started work on this project at AA-FTT 2009, we had to call it something. .NET versions of Java tools tend to get an N added somewhere, hence Cuke4Nuke. That’s all.

How to Install Cuke4Nuke

As of version 0.2.0, Cuke4Nuke is distributed as a Ruby Gem. To install it, do the following…

1. Download and install the .NET Framework 3.5 (comes with Visual Studio 2008).
2. Download and run the Ruby 1.8.7 one click installer, setting the option to add the Ruby executables to your path.
3. Install the Ruby installer Development Kit.
4. Open a command window and update RubyGems:

gem update -y --system --include-dependencies

5. Install win32console to get color in the command window:
gem install win32console

6. Install cuke4nuke:
gem install cuke4nuke --no-ri --no-rdoc

7. If you want Visual Studio integration, grab cuke4vs. You’ll get handy features like syntax highlighting, Intellisense, and jump to step definition.

How to Use It

There are two sides to using Cuke4Nuke: the Cucumber side and the .NET side.

The Cucumber side has a directory structure like this:

MyProject/features/
MyProject/features/some_feature.feature
MyProject/features/another_feature.feature
MyProject/features/step_definitions/
MyProject/features/step_definitions/cucumber.wire

The directories and the *.feature files are normal Cucumber stuff. The interesting bit is the .wire file. This tells Cucumber to go look for step definitions using the wire protocol instead of using the normal Ruby files. The .wire file has only two lines:

host: localhost
port: 3901

which specify the host and port to find the wire server with the Cucumber step definitions. (The default port for the Cuke4Nuke server is 3901. Use this in your .wire file unless you have a really good reason not to.)

You’ll need a version of Cucumber that includes the wire protocol language, which means 0.4.3 or newer (installed automatically with the cuke4nuke gem).

On the .NET side you need a DLL with step definitions. Step definitions are methods with one of the Cuke4Nuke.Framework step definition attributes (Given, When, or Then). For example:

[Then("^it should pass.$")]
public void ItShouldPass()
{
    Assert.Pass();
}

(The assertion is from NUnit, which is the only test framework Cuke4Nuke currently understands how to work with.)

Assuming you have a feature file that includes

Then it should pass.

when you run

> cuke4nuke MyProject\bin\Debug\MyStepDefinitionLibrary.dll

it should run Cucumber and cause Cuke4Nuke to invoke your ItShouldPass() method and show a successful test. You no longer have to run the Cuke4Nuke server and Cucumber separately. The cuke4nuke command does both for you.

Parameters

Capture groups in a step definition regular expression are passed as parameters to the step definition method. Parameters can be any type with a built-in TypeConverter (e.g. int, decimal, bool, etc.). For example:

[Given(@"^(\d+) cukes$")]
public void GivenSomeCukes(int cukes)
{
  _cukeCount = cukes;
}

Shared State

Most tests require some kind of shared state between steps. When a scenario is run, the same instance of a step definition class is used for each step invocation, so you can share state in private fields. For example:

public class CukeSteps
{
  int _cukeCount = 0;

  [Given(@"^(\d+) cukes$")]
  public void GivenSomeCukes(int cukes)
  {
    _cukeCount = cukes;
  }

  [When(@"^I add (\d+) more cukes$")]
  public void AddCukes(int cukes)
  {
    _cukeCount += cukes;
  }
}

As you get more step definitions, you’ll probably want to organize them into separate classes. You can share state between multiple step definition classes by requiring the same type of object in each class’s constructor. Cuke4Nuke will ensure that each step definition object gets the same instance of the dependency class. For example:

public class CukeJar
{
  public int CukeCount { get; set; }
}

public class Steps1
{
  CukeJar _cukeJar;

  public Steps1(CukeJar cukeJar)
  {
    _cukeJar = cukeJar;
  }

  [Given(@"^(\d+) cukes$")]
  public void GivenSomeCukes(int cukes)
  {
    _cukeJar.CukeCount = cukes;
  }

  [When(@"^I add (\d+) more cukes$")]
  public void AddCukes(int cukes)
  {
    _cukeJar.CukeCount += cukes;
  }
}

public class Steps2
{
  CukeJar _cukeJar;

  public Steps2(CukeJar cukeJar)
  {
    _cukeJar = cukeJar;
  }

  [Then(@"^I should have (\d+) cukes$")]
  public void ExpectCukes(int cukes)
  {
    Assert.That(_cukeJar.CukeCount, Is.EqualTo(cukes));
  }
}  

Executing

After installing the gem and creating your C# assembly, you will need to execute your features.

This can be achieved by using the single command ‘cuke4nuke’. The first argument of the command is the path to your C# assemblies containing your steps as described above. The second argument are standard cucumber arguments as you would normally provide, the example below provides the path to the features directory.

cuke4nuke examples/Calc/CalcFeatures/bin/Release/CalcFeatures.dll examples/Calc/CalcFeatures/features/