Phillip Trelford's Array

POKE 36879,255

Fixed Width Data Files

Scanning over Alvin Ashcraft’s excellent Morning Dew (a must read for .Net devs as is Chris Alcock’s Morning Brew), I came across a short article from Richard Carr on writing Fixed Width Data Files using C#.

Richard creates a class that inherits from StreamWriter, and all-in it’s just over 50 lines of idiomatic C# code:

using System;
using System.IO;
using System.Text;

public class FixedWidthWriter : StreamWriter
{
    public int[] Widths { get; set; }

    public char NonDataCharacter { get; set; }

    public FixedWidthWriter(
          int[] widths, string path, bool append, Encoding encoding)
        : base(path, append, encoding)
    {
        NonDataCharacter = ' ';
        Widths = widths;
    }

    public FixedWidthWriter(int[] widths, string file)
        : this(widths, file, false, Encoding.UTF8) { }

    public FixedWidthWriter(int[] widths, string file, bool append)
        : this(widths, file, append, Encoding.UTF8) { }

    public void WriteLine(string[] data)
    {
        if (data.Length > Widths.Length)
            throw new 
                InvalidOperationException("The data has too many elements.");

        for (int i = 0; i < data.Length; i++)
        {
            WriteField(data[i], Widths[i]);
        }
        WriteLine();
    }

    private void WriteField(string datum, int width)
    {
        char[] characters = datum.ToCharArray();
        if (characters.Length > width)
        {
            Write(characters, 0, width);
        }
        else
        {
            Write(characters);
            Write(new string(NonDataCharacter, width - characters.Length));
        }
    }
}

As you’d probably guess the same functionality takes half the lines to express in F#:

open System
open System.IO
open System.Text

type FixedWidthWriter(widths:int[], path:string, append, encoding) =
    inherit StreamWriter(path, append, encoding)
    member val Widths = widths with get, set
    member val NonDataCharacter = ' '  with get, set
    new(widths, file) = 
        new FixedWidthWriter(widths, file, false, Encoding.UTF8)
    new(widths, file, append) =
        new FixedWidthWriter(widths, file, append, Encoding.UTF8)
    member this.WriteLine(data:string[]) =
        if data.Length > this.Widths.Length
        then invalidOp "The data has too many elements."
        for i = 0 to data.Length-1 do      
            this.WriteField(data.[i], this.Widths.[i])
        base.WriteLine()
    member private this.WriteField(datum:string, width) =
        let xs = datum.ToCharArray()
        if xs.Length > width
        then base.Write(xs, 0, width)
        else        
            base.Write(xs)
            base.Write(String(this.NonDataCharacter, width - xs.Length))

The C# implementation uses classes and inheritance. In F# we’d typically favour composition over inheritance and start with the simplest possible thing that works, which in this case is a function that takes a file path, widths and the lines to write:

let WriteFixedWidth (path:string) (widths:int[]) (lines:string[] seq) =
    let pad = ' '
    use stream = new StreamWriter(path)
    let WriteField (datum:string) width =
        let xs = datum.ToCharArray()
        if xs.Length > width
        then stream.Write(xs, 0, width)
        else        
            stream.Write(xs)
            stream.Write(String(pad, width - xs.Length))
    for line in lines do
        for i = 0 to widths.Length-1 do 
            WriteField line.[i] widths.[i]
        stream.WriteLine()

The function is about half the size again and more closely follows YAGNI. To test it we can simply write:

let widths = [|20; 7; 6|]
[
[|"Company"; "Spend"; "Rating"|]
[|"Quality Foods Limited"; "1000000"; "Gold"|]
[|"The Pieman"; "50000"; "Silver"|]
[|"Bill's Fruit and Veg"; "10000"; "Bronze"|]
]
|> WriteFixedWidth "c:\\test.txt" widths

Does the language you chose make a difference?

Examples!

At the beginning of the month I gave a 30 minute talk at Cukeup!, an imaginatively named conference for the Cucumber community.

The talk was titled Example.Examples,Examples:

Talk about BDD and people often think about Given, When and Then. Mention Specification by Example and the focus shifts to tables. This talk will focus on the latter, showing the benefits of giving examples in tabular form for both collaboration and automation.
Expect to see real-world scenarios from a trading system, and hear how they were produced through collaboration between Business Analysts and Developers. You will also see how the examples were automated using the TickSpec library which includes a number of novel extensions to the Gherkin language.


Specification by Example

Back in 2002, Ward Cunningham developed the Framework for Integrated Test or Fit for short. With Fit or Fitnesse customers provide examples of how their software should work using ordinary business tools like Excel or a Wiki. The examples can then be automated via test fixtures.

In 2006, Dan North introduced BDD (behaviour-driven development) with it’s given, when, then nomenclature used by JBehave, RSpec and later Cucumber. Here the focus was on plain text while maintaining support for examples in tables via Wiki style markup using pipe ‘I’ delimited rows and columns.

2011 saw Gojko Adzic’s Specification by Example book offer a collaborative approach, that illustrates requirements through examples and encompasses automation with both Fit and BDD based tools.

TickSpec

.Net has seen it’s fair share of BDD libraries like Cuke4Nuke, NBehave, Raconteur, SpecFlow, StorEvil and TickSpec. Of these, in the BDD tagged Nuget package download charts SpecFlow is the current leader. I tend to think of TickSpec as Specflow’s ugly cousin, at least on the outside, there’s no pretty website, no Visual Studio add-in and it’s not going to win a popularity contest any time soon. On the inside though, TickSpec does have some redeemable qualities: it’s a lightweight, dependency free, extensible library that supports and extends Cucumber’s Gherkin language. Where SpecFlow uses the official gherkin parser via IKVM, TickSpec features it’s own parser written in a few 100 lines of F#. TickSpec’s parser builds a simple Abstract Syntax Tree (AST) for extensibility, a feature according to Aslak Hellesoy, Cucumber aims to emulate in the future.

SpecFlow also provides syntax colouring of feature files in Visual Studio, a feature based on Cuke4VS which was originally used with Cuke4Nuke. Cuke4VS and Cuke4Nuke are no longer under active development, however you can install the entire SpecFlow bundle to get Cuke4VS like syntax colouring for .feature files that works in Visual Studio 2010 or 2012 and then if you prefer use an alternative library like TickSpec for automation. TickSpec uses just-in-time compilation via Reflection.Emit so that you can set breakpoints in feature files, it therefore does not require SpecFlow’s code generation step which you should be able to disable from the Properties menu.

That said I’d recommend when writing features to step away from tools like Visual Studio and focus on collaborating with business stakeholders in an environment that everyone is comfortable in like a whiteboard, good old paper, Excel or a wiki. Also remember the testing pyramid and consider that not all scenarios will need to be automated, so starting in an automation environment is somewhat premature.

Combinatorial Examples

Circa 2009, NUnit can generate test cases for all possible combinations of data items via the CombinatorialAttribute, in fact it is the default:

let [<Test; Combinatorial>] MyTest
    ([<Values(1,2,3)>] x,
     [<Values("A","B")>] s) =
    () // ...

Along similar lines TickSpec generates all combinations of examples for a scenario:

Scenario: Winning positions
    Given a board layout:
        | 1 | 2 | 3    |
        | O | O | X |
        | O |   |   |
        | X |   | X |
    When a player marks X at <row> <col>
    And viewed with a <rotation> degree rotation
    Then X wins
    
Examples:
    | row    | col      | 
    | middle | right  |
    | middle | middle |
    | bottom | middle |

Examples:
    | rotation |
    | 0        |
    | 90       |
    | 180      |
    | 270      |

Here for each example of row and column, each rotation is also specified. It’s a bit like using database normalization for your examples, where data values are not repeated, and then applying a cross join when using the data items.

TickSpec also introduces the idea of Shared Examples, which can be shared across all scenarios in a feature file, just as Gherkin Backgrounds are.

F# Step Definitions

Step definitions wire up feature files with code, typically with regular expressions. TickSpec lets you write step definitions in either C# or F#. I find F# gives the better experience as you can specify method names with white space and symbols for matching lines in scenarios which keeps syntactic noise to a minimum.

Taking Pacman scoring as an example:

Feature: Pacman score

Scenario: Pacman eats dots
  When pacman eats a pac-dot
  Then he scores 10

Scenario: Pacman eats power pellets
  When pacman eats a power pellet
  Then he scores 50

The step definitions can be defined in a class or as below in an F# module:

let [<BeforeScenario>] SetupScenario () = 
    properties <- []

let [<When>] ``pacman eats a pac-dot`` () =
    properties <- PacDot::properties

let [<When>] ``pacman eats a power pellet`` () =
    properties <- PowerPellet::properties

let [<Then>] ``he scores (.*)`` (points:int) =
    let scored =
        properties |> List.sumBy (function
            | PacDot -> 10
            | PowerPellet -> 50
        )
    Assert.AreEqual(points, scored)

Getting Started

If you’re interested in Specification by Example, then I’d recommend taking a look at:

    If you decide to automate some examples, and like the sound of TickSpec I’d recommend starting by pulling the TickSpec.NUnit Nuget package into an F# library project. On the other hand if you find you’re not interacting with the business and spend all your time in Visual Studio I’d recommend doing plain old unit testing or using a fluent assertion library like Fluent Assertions, MSpec, FsUnit or NaturalSpec.

Fractal Zoom in Colour

A few years back I put together a simple Fractal Zoom in Silverlight using gray scales.

Time for a little makeover with color:


Hold down the mouse button over the Mandelbrot and move the mouse to highlight a rectangle, then release the mouse button to zoom in on that area.

Implementation

To get a nice colour progression I used the HSB color circle:

let H,S,L = 0.95 + (10.0 * n), 0.6, 0.5

Then created a colour lookup table using a list comprehension:

[|for i in 0..maxIteration ->
    let n = float i / float maxIteration
    let H,S,L = 0.95 + (10.0 * n), 0.6, 0.5
    let H = H - floor H
    let r,g,b = RGB.FromHSL(H,S,L)
    0xff000000 + (r <<< 16) + (g <<< 8) + b|]

For the HSL to RGB conversion I converted Colin Eberhardt’s accepted Stack Overflow answer from C# to F#:

C# F#
double v;
double r, g, b;
if (A > 1.0)
A = 1.0;

r = L;   // default to gray
g = L;
b = L;
v = 
   (L <= 0.5) 
   ? (L * (1.0 + S)) 
   : (L + S - L * S);
if (v > 0)
{
    double m;
    double sv;
    int sextant;
    double fract, vsf, mid1, mid2;

    m = L + L - v;
    sv = (v - m) / v;
    H *= 6.0;
    sextant = (int)H;
    fract = H - sextant;
    vsf = v * sv * fract;
    mid1 = m + vsf;
    mid2 = v - vsf;
    switch (sextant)
    {
       case 0:
        r = v;
        g = mid1;
        b = m;
        break;
       case 1:
        r = mid2;
        g = v;
        b = m;
        break;
       case 2:
        r = m;
        g = v;
        b = mid1;
        break;
       case 3:
        r = m;
        g = mid2;
        b = v;
        break;
       case 4:
        r = mid1;
        g = m;
        b = v;
        break;
       case 5:
        r = v;
        g = m;
        b = mid2;
        break;
    }
}
ColorRGB rgb = new ColorRGB();
rgb.R = Convert.ToByte(r * 255.0f);
rgb.G = Convert.ToByte(g * 255.0f);
rgb.B = Convert.ToByte(b * 255.0f);
rgb.A = Convert.ToByte(A * 255.0f);
return rgb;
let v = 
    if (L <= 0.5) 
    then (L * (1.0 + S)) 
    else (L + S - L * S)
if v > 0.0 then                
    let m = L + L - v;
    let sv = (v - m) / v;
    let H = H * 6.0;
    let sextant = int H
    let fract = H - float sextant
    let vsf = v * sv * fract;
    let mid1 = m + vsf;
    let mid2 = v - vsf;
    match sextant with
    | 0 -> v, mid1, m
    | 1 -> mid2, v, m
    | 2 -> m, v, mid1
    | 3 -> m, mid2, v
    | 4 -> mid1, m, v
    | 5 -> v, m, mid2
    | _ -> L, L, L
else L, L, L
|> fun (r,g,b) –> 
   byte(r*255.),
   byte(g*255.),
   byte(b*255.)

Voila, happy zooming :)