Sunday, July 24, 2011

Command line execution in storytests with fitSharp

A recent question on Stack Overflow asked if there is a command line execution fixture available for fitSharp. Something like:
|command line fixture|
|mypath\myprogram.exe|my arguments|
I answered that I didn't know of any but it would be easy to write one. (I put aside any thoughts of why this would be necessary. People use fitSharp for all kinds of things that I've never imagined.)

When I started to think more carefully, I realized that fitSharp provides the capability to do this without writing any fixtures at all. In classic Fit, the first cell in a table is the name of a fixture class to be invoked. In fitSharp, if this cell does not contain the name of a fixture class, a DoFixture is created which lets us execute methods on a class without writing a fixture. So we can write a command line class:
using System.Diagnostics;
namespace myStuff {
    public class CommandLine {
        public void Run(string program, string arguments) {
            var process = Process.Start(program, arguments);
            process.WaitForExit();
        }
    }
}
Then our test looks like:
|myStuff.CommandLine|
|run|mypath\myprogram.exe||my arguments|
This is a common pattern: we write a 'domain adapter' class to make it easier to invoke methods on our system under test from standard fixtures like DoFixture. These classes tend to be more flexible and reusable than if we write custom fixtures for each of our test scenarios.

But we can go further than this. We can execute methods on the System.Diagnostics classes directly. The 'with' keyword tells DoFixture which object to execute methods on. So our test can be:
|with|type|System.Diagnostics.Process|
|with|start|mypath\myprogram.exe||my arguments|
|wait for exit|
Of course, it would be nice to not duplicate this throughout our tests, so we can define a procedure:
|define|run|@program|with|@arguments|
|with|type|System.Diagnostics.Process|
|with|start|@program||@arguments|
|wait for exit|
Then we can use this whenever we need to run a program:
|run|mypath\myprogram.exe|with|my arguments|
This is a simple example of how we can start building a testing DSL that suits the kind of test scenarios we need to execute.

4 comments:

  1. If we use with, do we still need to create a 'with' class?

    I get the folllowing error:

    with Method withsystemdiagnosticsprocess not found in fitSharp.Slim.Operators.InvokeInstructionBase+NullInstance

    Thanks

    ReplyDelete
  2. This post describes Fit tests, not Slim tests.

    ReplyDelete
    Replies
    1. Hi Mike,

      I want to execute a sql query (select statement) retrieved from a database table, stored in a >> variable (DBFit) and then execute it but it does not work (screenshot of the test posted on the DBFit Google group. The DBFit script is -
      !|query|select query from tbl_RuleDetails as tr Left OUTER Join tbl_Rule as trd on tr.ruleId=trd.ruleId where tr.ruleId=12|
      |query?|
      |>>q|

      !|query|<>t|

      where query is the database table column that contains a SQL query, read into >>q, which I am trying to execute in the second table and obtain TransactionId).

      I wanted to contact you to see if I could contribute in incorporating this into DBFit as a command, when I came across this post of yours.

      It seems to solve my requirement, if I run Sqlcmd in a process but how to obtain the results and use it as a table in DBFit ? Or, should I run a .net SQLCommand and obtain the results as a datatable to use/compare/test the results in DBFit?

      Ps: "This post describes Fit tests, not Slim tests" but the C# class (namespace myStuff {...) will use FitSharp, right? And not Fit?

      Thanks in advance for help and speedy rply,

      Ravichandran Jv

      Delete
  3. Can you post a link to your screenshot?

    ReplyDelete