Rash thoughts about .NET, C#, F# and Dynamics NAV.


"Every solution will only lead to new problems."

Saturday, 24. April 2010


Solving KataYahtzee with F# and NaturalSpec

Filed under: F#,Informatik,Kata — Steffen Forkmann at 19:04 Uhr

Today I’m starting a new blog post series about solving code katas in F# and with the help of my NaturalSpec project. A code kata is a programming exercise which helps to improve your skills through practice and repetition. In this series we want to use the Test Driven Development TDD approach which means in the context of NaturalSpec that we have to write our specs before we implement the algorithm.

Problem Description

“The game of yahtzee is a simple dice game. Each round, each player rolls five six sided dice. The player may choose to reroll some or all of the dice up to three times (including the original roll). The player then places the roll at a category, such as ones, twos, sixes, pair, two pairs etc. If the roll is compatible with the score, the player gets a score for this roll according to the rules. If the roll is not compatible, the player gets a score of zero for this roll.

The kata consists of creating the rules to score a roll in any of a predefined category. Given a roll and a category, the final solution should output the score for this roll placed in this category.”

[codingdojo.org]

Category 1 – Ones, Twos, Threes, Fours, Fives, Sixes

“Ones, Twos, Threes, Fours, Fives, Sixes: The player scores the sum of the dice that reads one, two, three, four, five or six, respectively. For example, 1, 1, 2, 4, 4 placed on "fours" gives 8 points.”

After reading this category description we could come up with the following spec:

module Yahtzee.Specs

 

open NaturalSpec

 

let placed_on category list =

    printMethod category

    calcValue category list

 

[<Scenario>]    

let “Given 1,1,2,4,4 placed on "fours" gives 8 points.“ () =  

    Given (1, 1, 2, 4, 4)

      |> When (placed_on Fours)

      |> It should equal 8

      |> Verify

Since we really want to implement six different categories we should also add some more scenarios like this one:

[<Scenario>]    

let “Given 1,1,6,4,6 placed on "sixes" gives 12 points.“ ()=  

    Given (1, 1, 6, 4, 6)

      |> When (placed_on Sixes)

      |> It should equal 12

      |> Verify

 

// …

Now we have some specs but they will all fail since we don’t have anything implemented yet. So we have to come up with a model of dice rolls and categories. As the specs suggests we model the dice roll as a tuple of ints and the category as a discriminated union:

module Yahtzee.Model

 

type Roll = int * int * int * int * int

 

type Category =

| Ones

| Twos

| Threes

| Fours

| Fives

| Sixes  

The tuple is a natural choice for the dice roll, but for easier calculation we add a helper function which converts it into a list. This allows use to use the standard list functions and therefore summing the values becomes trivial:

let toList (roll:Roll) =

    let a,b,c,d,e = roll

    [a;b;c;d;e]

 

let sumNumber number =

    Seq.filter ((=) number)

      >> Seq.sum

 

let calcValue category roll =

    let list = toList roll

    match category with

    | Ones   -> sumNumber 1 list

    | Twos   -> sumNumber 2 list

    | Threes -> sumNumber 3 list

    | Fours  -> sumNumber 4 list

    | Fives  -> sumNumber 5 list

    | Sixes  -> sumNumber 6 list

Now we can run our scenarios with any NUnit runner. I’m using the default NUnit GUI runner here, which gives me a picture like this:

Both specs in NUnit

Category 2 – Pair

“Pair: The player scores the sum of the two highest matching dice. For example, 3, 3, 3, 4, 4 placed on "pair" gives 8.”

The kata description gives us some new scenarios. As seen above we should specify them before writing the code.

[<Scenario>]    

let “Given 3,3,3,4,4 placed on "pair" gives 8.“ () =  

    Given (3, 3, 3, 4, 4)

      |> When (placed_on Pair)

      |> It should equal 8

      |> Verify

 

[<Scenario>]    

let “Given 5,3,5,4,4 placed on "pair" gives 10.“ () =  

    Given (5, 3, 5, 4, 4)

      |> When (placed_on Pair)

      |> It should equal 10

      |> Verify   

 

[<Scenario>]    

let “Given 1,2,3,4,5 placed on "pair" gives 0.“ () =  

    Given (1, 2, 3, 4, 5)

      |> When (placed_on Pair)

      |> It should equal 0

      |> Verify     

Since we use a new category we now have to extend our model and the calcValue function:

type Category =

| Ones

  // …

| Sixes

| Pair

 

// …

let sumAsPair list number =

    let numberCount =

        list

          |> Seq.filter ((=) number)

          |> Seq.length

 

    if numberCount >= 2 then 2 * number else 0

 

let calcValue category roll =

    let list = toList roll

    match category with

    | Ones   -> sumNumber 1 list

        // …

    | Sixes  -> sumNumber 6 list

    | Pair   ->

        [1..6]

          |> Seq.map (sumAsPair list)

          |> Seq.max  

Category 3 – Two pairs

“Two pairs: If there are two pairs of dice with the same number, the player scores the sum of these dice. If not, the player scores 0. For example, 1, 1, 2, 3, 3 placed on "two pairs" gives 8.”

[<Scenario>]    

let “Given 1,1,2,3,3 placed on "two pair" gives 8.“ () =  

    Given (1, 1, 2, 3, 3)

      |> When (placed_on TwoPair)

      |> It should equal 8

      |> Verify

 

[<Scenario>]    

let “Given 1,6,6,3,3 placed on "two pair" gives 18.“ () =  

    Given (1, 6, 6, 3, 3)

      |> When (placed_on TwoPair)

      |> It should equal 18

      |> Verify

 

[<Scenario>]    

let “Given 1,1,2,4,3 placed on "two pair" gives 0.“ () =  

    Given (1, 1, 2, 4, 3)

      |> When (placed_on TwoPair)

      |> It should equal 0

      |> Verify 

Implementing this category is a little bit tricky but with the help of our Pair function and some more standard sequence combinators we can get our spec green:

type Category =

| Ones

  // …

| TwoPair

 

let allPairs =

    [for i in 1..6 do

       for j in 1..6 -> i,j]

 

let calcValue category roll =

    // …

    | TwoPair   ->

        allPairs

          |> Seq.filter (fun (a,b) -> a <> b)

          |> Seq.map (fun (a,b) ->

                let a’ = sumAsPair list a

                let b’ = sumAsPair list b

                if a’ = 0 || b’ = 0 then 0 else a’ + b’)

          |> Seq.max    

Category 4 – Three of a kind

“Three of a kind: If there are three dice with the same number, the player scores the sum of these dice. Otherwise, the player scores 0. For example, 3, 3, 3, 4, 5 places on "three of a kind" gives 9.”

[<Scenario>]    

let “Given 3,3,3,4,5 placed on "three of a kind" gives 9“()=  

    Given (3, 3, 3, 4, 5)

      |> When (placed_on ThreeOfAKind)

      |> It should equal 9

      |> Verify

 

[<Scenario>]    

let “Given 3,4,3,4,5 placed on "three of a kind" gives 0“()=  

    Given (3, 4, 3, 4, 5)

      |> When (placed_on ThreeOfAKind)

      |> It should equal 0

      |> Verify

Now it is time to refactor our code. The sumAsPair function should be extended to a sumAsTuple function:

type Category =

| Ones

  // …

| ThreeOfAKind

 

let sumAsTuple value list number =

    let numberCount =

        list

          |> Seq.filter ((=) number)

          |> Seq.length

 

let takeBestTuple value list =

    [1..6]

        |> Seq.map (sumAsTuple value list)

        |> Seq.max 

    if numberCount >= value then value * number else 0

 

let calcValue category roll =

      // …

    | Pair   -> takeBestTuple 2 list

    | TwoPair   ->

        allPairs

          |> Seq.filter (fun (a,b) -> a <> b)

          |> Seq.map (fun (a,b) ->

                let a’ = sumAsTuple 2 list a

                let b’ = sumAsTuple 2 list b

                if a’ = 0 || b’ = 0 then 0 else a’ + b’)

          |> Seq.max

    | ThreeOfAKind –> takeBestTuple 3 list

Category 5 – Four of a kind

“Four of a kind: If there are four dice with the same number, the player scores the sum of these dice. Otherwise, the player scores 0. For example, 2, 2, 2, 2, 5 places on "four of a kind" gives 8.”

[<Scenario>]    

let “Given 2,2,2,2,5 placed on "four of a kind" gives 8“ ()=  

    Given (2, 2, 2, 2, 5)

      |> When (placed_on FourOfAKind)

      |> It should equal 8

      |> Verify

 

[<Scenario>]    

let “Given 2,6,2,2,5 placed on "four of a kind" gives 0“ ()=  

    Given (2, 6, 2, 2, 5)

      |> When (placed_on FourOfAKind)

      |> It should equal 0

      |> Verify  

With the help of the takeBestTuple function this becomes trivial:

type Category =

| Ones

  // …

| FourOfAKind

 

let calcValue category roll =

      // …

    | FourOfAKind  -> takeBestTuple 4 list

 

Category 6 – Small straight

“Small straight: If the dice read 1,2,3,4,5, the player scores 15 (the sum of all the dice), otherwise 0.”

[<Scenario>]    

let “Given 1,2,3,4,5 placed on "Small Straight" gives 15“()=  

    Given (1,2,3,4,5)

      |> When (placed_on SmallStraight)

      |> It should equal 15

      |> Verify

 

[<Scenario>]    

let “Given 1,2,5,4,3 placed on "Small Straight" gives 15“()=  

    Given (1,2,5,4,3)

      |> When (placed_on SmallStraight)

      |> It should equal 15

      |> Verify

 

[<Scenario>]    

let “Given 1,2,6,4,3 placed on "Small Straight" gives 0“()=  

    Given (1,2,6,4,3)

      |> When (placed_on SmallStraight)

      |> It should equal 0

      |> Verify 

As in all the above scenarios we don’t assume any specific order in our rolls but for this category it is easier to test if the data is sorted:

type Category =

| Ones

  // …

| SmallStraight

 

let calcValue category roll =

      // …

    | SmallStraight ->

        match list |> List.sort with

        | [1;2;3;4;5] -> 15

        | _ -> 0

Category 7 – Large straight

“Large straight: If the dice read 2,3,4,5,6, the player scores 20 (the sum of all the dice), otherwise 0.”

[<Scenario>]    

let “Given 2,3,4,5,6 placed on "Large Straight" gives 20“()=  

    Given (2,3,4,5,6)

      |> When (placed_on LargeStraight)

      |> It should equal 20

      |> Verify

 

[<Scenario>]    

let “Given 6,2,5,4,3 placed on "Large Straight" gives 20“()=  

    Given (6,2,5,4,3)

      |> When (placed_on LargeStraight)

      |> It should equal 20

      |> Verify

 

[<Scenario>]    

let “Given 1,2,6,4,3 placed on "Large Straight" gives 0“()=  

    Given (1,2,6,4,3)

      |> When (placed_on LargeStraight)

      |> It should equal 0

      |> Verify 

Of course the implementation is exactly the same as for the small straight:

type Category =

| Ones

  // …

| LargeStraight

 

let calcValue category roll =

      // …

    | LargeStraight ->

        match list |> List.sort with

        | [2;3;4;5;6] -> 20

        | _ -> 0

Category 8 – Full house

“Full house: If the dice are two of a kind and three of a kind, the player scores the sum of all the dice. For example, 1,1,2,2,2 placed on "full house" gives 8. 4,4,4,4,4 is not "full house".”

[<Scenario>]    

let “Given 1,1,2,2,2 placed on "full house" gives 8.“ () =  

    Given (1,1,2,2,2)

      |> When (placed_on FullHouse)

      |> It should equal 8

      |> Verify

 

[<Scenario>]    

let “Given 4,4,4,4,4 placed on "full house" gives 0.“ () =  

    Given (4,4,4,4,4)

      |> When (placed_on FullHouse)

      |> It should equal 0

      |> Verify

 

[<Scenario>]    

let “Given 1,1,2,3,2 placed on "full house" gives 0.“ () =  

    Given (1,1,2,3,2)

      |> When (placed_on FullHouse)

      |> It should equal 0

      |> Verify

Implementing the FullHouse category is easy if we reuse our solutions to the Two pairs category:

type Category =

| Ones

  // …

| FullHouse

 

let takeBestCombo value1 value2 list =

    allPairs

        |> Seq.filter (fun (a,b) -> a <> b)

        |> Seq.map (fun (a,b) ->

            let a’ = sumAsTuple value1 list a

            let b’ = sumAsTuple value2 list b

            if a’ = 0 || b’ = 0 then 0 else a’ + b’)

        |> Seq.max

 

let calcValue category roll =

      // …

    | TwoPair   -> takeBestCombo 2 2 list

      // …

    | FullHouse   -> takeBestCombo 2 3 list

Category 9 – Yahtzee

“Yahtzee: If all dice are the have the same number, the player scores 50 points, otherwise 0.”

Here we can use NaturalSpec’s ScenarioTemplates in order to specify all Yahtzees:

[<ScenarioTemplate(1)>]

[<ScenarioTemplate(2)>]

[<ScenarioTemplate(3)>]

[<ScenarioTemplate(4)>]

[<ScenarioTemplate(5)>]

[<ScenarioTemplate(6)>]

let “Given n,n,n,n,n placed on "Yahtzee" gives 50.“ n =  

    Given (n,n,n,n,n)

      |> When (placed_on Yahtzee)

      |> It should equal 50

      |> Verify

 

[<Scenario>]    

let “Given 1,1,1,2,1 placed on "Yahtzee" gives 50.“ () =  

    Given (1,1,1,2,1)

      |> When (placed_on Yahtzee)

      |> It should equal 0

      |> Verify

The implementation is pretty easy:

type Category =

| Ones

  // …

| Yahtzee

 

let calcValue category roll =

      // …

    | Yahtzee ->

        let a,b,c,d,e = roll

        if a = b && a = c && a = d && a = e then 50 else 0

Category 10 – Chance

“Chance: The player gets the sum of all dice, no matter what they read.”

[<Scenario>]    

let “Given 1,1,1,2,1 placed on "Chance" gives 6.“ () =  

    Given (1,1,1,2,1)

      |> When (placed_on Chance)

      |> It should equal 6

      |> Verify

 

[<Scenario>]    

let “Given 1,6,1,2,1 placed on "Chance" gives 11.“ () =  

    Given (1,6,1,2,1)

      |> When (placed_on Chance)

      |> It should equal 11

      |> Verify

This seems to be the easiest category as we only have to sum the values:

type Category =

| Ones

  // …

| Chance

 

let calcValue category roll =

      // …

    | Chance -> List.sum list

Conclusion

We used a lot of F#’s sequence combinators, pattern matching and discriminated unions in this kata. I think this shows that F# is very well suited for such a problem and with NaturalSpec we can easily use a TDD/BDD approach.

The complete source code can be found in the NaturalSpec repository.

If you want to know more about a specific part of the kata or NaturalSpec feel free to contact me.

Tags: , , , , , , ,

Sunday, 8. November 2009


"Getting started" with NaturalSpec – (Updated 08.11.2009)

Filed under: .NET,F#,NaturalSpec — Steffen Forkmann at 10:48 Uhr

In my last article (Introducing NaturalSpec – A Domain-specific language (DSL) for testing) I used NaturalSpec in two small samples. This time I will show how we can set up a NaturalSpec environment to write our first automatically testable scenarios.

1. Choosing an IDE

The first step is to choose an integrated development environment for NaturalSpec. At the current project status you should be able to use NaturalSpec with Visual Studio 2008, Visual Studio 2010 beta 2, the freely available Visual Studio 2008 Shell or the free IDE SharpDevelop 3.0.

2. Installing the testing framework

As NaturalSpec uses NUnit as the underlying testing framework we have to install NUnit 2.5. I also recommend installing TestDriven.Net in order to get a Unit Test runner within Visual Studio.

3. Installing F#

NaturalSpec is completely written in F# and all specs will also be written in F#. This doesn’t imply you have to learn programming in F# but we need the F# compiler to get things working. You can download the F# October 2009 CTP from the Microsoft F# Developer Center.

4. Downloading the latest version of NaturalSpec

You can download a .zip with the latest NaturalSpec libraries from GoogleCode.

5. Creating a spec

This part is written for using Visual Studio 2008. If you use SharpDevelop or Visual Studio 2008 Shell this might differ in some detail.

Start Visual Studio 2008 and create a new F# class library.

Creating a spec project

Rename Module1.fs in ListSpec.fs and delete script.fsx from the project:

Solution explorer

Create a folder “Lib” and unzip the NaturalSpec libraries into it.

Add NaturalSpec.dll and nunit.framework.dll as references to your project:

Adding project references

Copy the following code into ListSpec.fs:

module ListSpec
open NaturalSpec

[<Scenario>]
let When_removing_an_3_from_a_small_list_it_should_not_contain_3() =
  Given [1;2;3;4;5]
    |> When removing 3
    |> It shouldn't contain 3
    |> Verify

If you have TestDriven.Net installed you can run your spec via right click in the solution explorer:

Run spec with TestDriven.net

If you don’t like the TestDriven.Net test runner you might want to use the NUnit GUI runner. The output should look like:

NUnit Gui runner

In addition the test runner should produce a Spec output file with the name “Spec.txt” within the same folder.

Summary

In a minimal environment you need SharpDevelop, the F# compiler, NUnit and the NaturalSpec libraries for using NaturalSpec.

In the next post I will show how you can use NaturalSpec to create a spec for C# projects.

Tags: , , , , ,

Sunday, 18. October 2009


xUnit.net support in “FAKE – F# Make” 0.14

Filed under: F#,FAKE - F# Make — Steffen Forkmann at 18:09 Uhr

Yesterday I released “FAKE – F# Make” version 0.14 with xUnit.net support. The usage is very easy and similar to the usage of NUnit:

Target "xUnitTest" (fun () -> 

  let testAssemblies =

    !+ (testDir + @"\Test.*.dll")

      |> Scan

 

  xUnit

    (fun p ->

       {p with

           ShadowCopy = false;

           HtmlPrefix = testDir})

    testAssemblies 

)

This sample works perfectly with TeamCity and creates a html-page per test project in addition:

TeamCity output

HMTL output

If you want to publish the xUnit.net test results in CruiseControl.NET just modify the build script a little:

Target "xUnitTest" (fun () -> 

  let testAssemblies =

    !+ (testDir + @"\Test.*.dll")

      |> Scan

 

  xUnit

    (fun p ->

       {p with

           ShadowCopy = false;

           HtmlPrefix = testDir;

           XmlPrefix = testDir })

    testAssemblies 

)

Now follow the steps in the CrusieControl.NET documentation. You will need to download the xUnitSummary.xsl file and save it to your webdashboard directory. If everything works correctly you should see something like this:

CruisControl.NET output

Tags: , , , , ,

Wednesday, 15. April 2009


Integrating a “FAKE – F# Make” build script into TeamCity

Filed under: F#,FAKE - F# Make,Tools,Visual Studio — Steffen Forkmann at 11:00 Uhr

This artile has been moved to http://fsharp.github.io/FAKE/teamcity.html

Tags: , , , , , , ,

Wednesday, 1. April 2009


Getting started with “FAKE – F# Make” – Get rid of the noise in your build scripts.

Filed under: C#,English posts,F#,FAKE - F# Make,Informatik,NaturalSpec,Tools — Steffen Forkmann at 21:02 Uhr

This article has been moved to http://fsharp.github.io/FAKE/gettingstarted.html

Tags: , , , , , , ,

Saturday, 28. February 2009


Parameterized Scenarios with NaturalSpec

Filed under: F#,NaturalSpec — Steffen Forkmann at 16:46 Uhr

I wrote a lot about NaturalSpec in my last articles. This time I will show how we can use parameterized scenarios.

1. Using predefined scenarios

By writing predefined parameterized scenarios we can easily create a scenario suite with lots of different test cases:

// predefined scenario
let factorialScenario x result =
  Given x
    |> When calculating factorial
    |> It should equal result

[<Scenario>]
let When_calculation_factorial_of_1() =
  factorialScenario 1 1
    |> Verify   

[<Scenario>]
let When_calculation_factorial_of_10() =
  factorialScenario 10 3628800
    |> Verify

If we run these scenarios with NUnit we will get the following output:

Scenario: When calculation factorial of 1

  – Given 1

    – When calculating factorial

       => It should equal 1

==> OK

==> Time: 0.0093s

Scenario: When calculation factorial of 10

  – Given 10

    – When calculating factorial

       => It should equal 3628800

==> OK

==> Time: 0.0018s

2. Using the ScenarioTemplate attribute

The second and shorter option is to use the ScenarioTemplate attribute, which is inherited from NUnit’s new TestCase attribute:

// with ScenarioTemplate Attribute
[<ScenarioTemplate(1, 1)>]
[<ScenarioTemplate(2, 2)>]
[<ScenarioTemplate(5, 120)>]
[<ScenarioTemplate(10, 3628800)>]
let When_calculating_fac_(x,result) =
  Given x
    |> When calculating factorial
    |> It should equal result
    |> Verify

This code will create 4 different scenarios, which NUnit will display and report separately:

NUnit runner reports test cases

3. Using ScenarioSource

The third option is to use the ScenarioSource attribute. Here we define a function which generates TestData:

/// with a scenario source      
let MyTestCases =
  TestWith 12 3 4
    |> And 12 4 3
    |> And 12 6 2
    |> And 1200 40 30
    |> And 0 0 0 |> ShouldFailWith (typeof<System.DivideByZeroException>)

And then we have to tell NaturalSpec which TestData a scenario should use:

[<Scenario>]
[<ScenarioSource "MyTestCases">]
let When_dividing a b result =
 Given a 
   |> When dividing_by b
   |> It should equal result
   |> Verify
 NaturalSpec with ScenarioSource  
Summary

Sometime it makes sense to test a scenario with a bunch of different parameters. We can use the ScenarioTemplate attribute to easily parameterize our scenarios. If we want more flexibility we can use predefined scenarios with custom parameters or the ScenarioSource attribute.

Tags: , , , ,

Monday, 23. February 2009


Introducing NaturalSpec – A Domain-specific language (DSL) for testing – Part I

Filed under: C#,F#,NaturalSpec,Tools — Steffen Forkmann at 11:31 Uhr

Test-Driven development (TDD) is a well known software development technique and follows the mantra “Red-Green-Refactor”. Behavior-Driven Development (BDD) is a response to TDD and introduces the idea of using natural language to express the Unit Test scenarios.

There are a lot of popular testing frameworks around which can be used for BDD including xUnit.net ,NUnit, StoryQ, MSpec, NSpec and NBehave. Most of them can be used with fluent interfaces and therefore provides a good readability of the sources. Some of them even provide the possibility to generate a spec in natural language out of passed Unit tests.

What is a spec?

“A specification is an explicit set of requirements to be satisfied by a material, product, or service.”

American Society for Testing and Materials (ASTM) definition

A spec is an important document for the communication process – it enables domain experts to communicate with developers. But how can you verify the compliance with the spec? The answer is: you have to write unit tests. Even with the mentioned frameworks there is a lot of work to do in order to translate a spec scenario into a Unit Test.

Question 7 in the famous Joel Test is “Do you have a spec?”.

The idea of NaturalSpec is to give domain experts the possibility to express their scenarios directly in compilable Unit Test scenarios by using a Domain-specific language (DSL) for Unit Tests. NaturalSpec is completely written in F# – but you don’t have to learn F# to use it. You don’t even have to learn programming at all.

Example 1 – Specifying a list

Let’s consider a small example. If we want to test a new List implementation a spec could look like this:

[<Scenario>]
let When_removing_an_3_from_a_small_list_it_should_not_contain_3() =
  Given [1;2;3;4;5]              // “Arrange” test context
    |> When removing 3           // “Act|> It shouldn't contain 3    // “Assert|> It should contain 4       // another assertion
    |> Verify                    // Verify scenario

I used BDD style here and expressed my scenario in a quite natural language. As the comments are indicating the scenario is following the Arrange Act Assert (“AAA”) pattern.

With the Keyword “Given” I can create a test context (the objects I want to test). In this sample I created a list with 5 elements. With the keyword “When” I call a function which does something with my test context. In this case I want to remove the value 3. In the Assert section (keywords “It should” or “It shouldn’t”) I can give some observations, which should hold for my manipulated test context.

When I run this scenario via a NUnit runner (i am using TestDriven.Net) I get the following output:

Scenario: When removing an 3 from a small list it should not contain 3

– Given [1; 2; 3; 4; 5]
– When removing 3
=> It should not contain 3
=> It should contain 4
==> OK

Example 2 – Specifying a factorial function

If you implement factorial function the spec could look like this:

[<Scenario>]
let When_calculating_fac_5_it_should_equal_120() =
  Given 5
    |> When calculating factorial
    |> It should equal 120
    |> Verify    

[<Scenario>]
let When_calculating_fac_1_it_should_equal_1() =
  Given 1
    |> When calculating factorial
    |> It should equal 1
    |> Verify          

[<Scenario>]
let When_calculating_fac_0_it_should_equal_0() =
  Given 0
    |> When calculating factorial
    |> It should equal 1
    |> Verify

And the output of NaturalSpec would look like this:

Scenario: When calculating fac 0 it should equal 0

– Given 0
– When calculating factorial
=> It should equal 1
==> OK

Scenario: When calculating fac 1 it should equal 1

– Given 1
– When calculating factorial
=> It should equal 1
==> OK

Scenario: When calculating fac 5 it should equal 120

– Given 5
– When calculating factorial
=> It should equal 120
==> OK

Getting started

Of course you can use NaturalSpec to specify C# objects. I see my post "Using NaturalSpec to create a spec for C# projects" for a small sample.

You can download NaturalSpec at GoogleCode and follow the “Getting started” tutorial in order to write your first automatically testable spec.

I am very interested in your feedback. Do you like the syntax? What should I change? Do you consider using a spec tool like NaturalSpec?

Tags: , , , , , , , , , , ,

Sunday, 11. January 2009


ReSharper 4.5 and F#

Filed under: F#,Tools — Steffen Forkmann at 19:16 Uhr

Since I am working with hybrid solutions (with F# and C# projects in it) I had to deactivate ReSharper. ReSharper had a problem with analyzing my F# sources (see JIRA bug entry #79203). The result was that every single F# defined type and function was marked as an error. I nearly got crazy. On one hand I got used to all the nice ReSharper refactorings (and the NUnit runner) and on the other I got all these false positive errors.

But from now on this hard times are over. Today I tested build 1153 (see nightly builds for version 4.5) – and everything works fine.

ReSharper is running again

Thank you guys at JetBrains. 🙂

Tags: , ,

Thursday, 8. January 2009


How I do Continuous Integration with my C# / F# projects – part III: Running automated UnitTests

Filed under: C#,English posts,F#,Tools,Visual Studio — Steffen Forkmann at 19:13 Uhr

In the last two posts I showed how to set up a Subversion (part I: Setting up Source Control) and a TeamCity server (part II: Setting up a Continuous Integration Server).

This time I will show how we can integrate NUnit to run automated test at each build. TeamCity supports all major Testing Frameworks (including MS Test) but I will concentrate on NUnit here.

"NUnit is a unit-testing framework for all .Net languages. Initially ported from JUnit, the current production release, version 2.4, is the fifth major release of this xUnit based unit testing tool for Microsoft .NET. It is written entirely in C# and has been completely redesigned to take advantage of many .NET language features, for example custom attributes and other reflection related capabilities. NUnit brings xUnit to all .NET languages."

[product homepage]

Creating a TestProject

First of all download and install NUnit 2.4.8 (or higher) from http://www.nunit.org/.

Now we add a small function to our F# source code:

let rec factorial = function  
  | 0 -> 1
  | n when n > 0 -> n * factorial (n-1)
  | _ -> invalid_arg "Argument not valid"

This is the function we want to test. We add a new C# class library to our solution (e.g. “TestCITestLib” 😉 ) and add a reference to nunit.framework. Inside this new TestLibrary we add a TestClass with the following code:

namespace TestCITestLib
{
    using NUnit.Framework;

    [TestFixture]
    public class FactorialTest
    {
        [Test]
        public void TestFactorial()
        {
            Assert.AreEqual(1, Program.factorial(0));
            Assert.AreEqual(1, Program.factorial(1));
            Assert.AreEqual(120, Program.factorial(5));
        }

        [Test]
        public void TestFactorialException()
        {
            Program.factorial(-1);
        }
    }
}

To ensure the build runner is able to compile our solution we put the nunit.framework.dll near to our TestProject and commit our changes.

Adding Nunit.framework.dll

Configure TeamCity for UnitTesting

The next step is to tell TeamCity that the build runner should run our UnitTests:

Configure build runner for NUnit

If we now run the build we should get the following error:

UnitTest error during automated build

Our second test function failed, because we didn’t expect the System.ArgumentException. We can fix this issue by adding the corresponding attribute to the Testfunction:

[Test,
 ExpectedException(typeof(System.ArgumentException))]
public void TestFactorialException()
{
    Program.factorial(-1);
}0

Tests passed

Configure the build output

At this point we have a minimalistic Continuous Integration infrastructure. Every time someone performs a Commit on our repository a automated build will be started and the sources will be tested against the given UnitTests. Now we should concentrate on getting our build output – the artifacts. The term artifact is usually used to refer to files or directories produced during a build. Examples of such artifacts are:

  • Binaries (*.exe, *.dll)
  • Software packages and installers (*.zip, *.msi)
  • Documentation files (e.g. help files)
  • Reports (test reports, coverage reports, …)

At this time we are only interested in the binaries (this means CITestLib.dll). We can add the following artifact definition to our TeamCity project:

Configure artifacts in TeamCity

If we now rebuild our solution the build runner collects the configured artifacts and stores them with all build information:

Collected artifacts

Next time I will show how we can add more artifacts – e.g. an automated documentation.

Tags: , , , , , , , , ,

Saturday, 12. November 2005


NUnit mit dem Visual Studio 2005

Filed under: .NET,Visual Studio — Steffen Forkmann at 9:44 Uhr

Obwohl ja VS 2005 in der Tester Edition Unittesting von Hause aus unterstützt, bleibt für die preiswerteren Editionen (z.B. Professional und Express) immernoch NUnit als Alternative. Dort gibt es jedoch selbst in der Version 2.2.2 noch leichte Komplikationen bei der Installation mit .NET 2.0.

Charlie Calvert erklärt in seinem Blog ausführlich, wie man das NUnit-Framework auch unter .NET 2.0 lauffähig bekommt.

Tags: , ,