Monday, 24 August 2015

Automated Testing a WCF Service

Slightly, ok very, off topic but this is something I've been working on today and I need to blog about it before I forget what I did!

I need to create a test harness for testing one method on a pre-existing web service.  That web service even comes with a test harness in the code but it's very old-school .Net and I can't fathom it - or learn for myself if I just try and pick it up.

There were several things I had to learn to do:-
1. Consume/wire up to the WCF service.
2. Read in test data from an input file.

Consuming a WCF Service

This was harder - or at least took me longer - than it should have been.  It helps if you're in a Unit Test project, rather than a class library (doh!) and in the end was relatively simple - when you know how.  I referred to the section "Accessing a service" at this page https://msdn.microsoft.com/en-us/library/bb386386.aspx to help.  It was the first I found that talked about adding a Service Reference.  Prior to that I was using the svcutil tool to create a client class, but still had some problems with that.  It looked like it was going to work but I went the "Add a Service Reference" route.

The beauty of programmatically testing a service is that in code it is just another class, and its public methods exposed are methods of that class.  So you just need to create an instance of that class and you can call its methods.  Don't forget to close  it!  I used [TestInitalize] and [TestCleanup] methods to ensure I did this properly.

A few quick tests proved I was able to all the service, receive an answer and Assert if it was right or not.  Now to automate the data input from a file.

Read in test data from an input file

Again a microsoft page was a huge help - Walkthrough: Using a configuration file to define a data source.  It struck me as odd that I found Microsoft resources more useful that StackOverflow.  I guess there's a first time for everything...

Several steps are required here, and it took some jiggery pokery to run correctly on my system but it worked.  Perhaps most imporantly, I don't (yet) understand all the decorators that were suggested.


  • Update app.config with custom configuration settings.  Follow through the notes in the above link, bear in mind that at the end of that page is a complete example you can copy and paste.  In summary you need to create something like this:-

A <configuration> section containing
        <configSections> /// Standard text for a named section
        <connectionStrings>
        <named section>  /// <microsoft.visualstudio.testtools> is the standard text
              <dataSources>

I've used the full path to my input file in the connectionString attribute of the add element, with escaped backslashes \\ in the path.  I've used an excel spreadsheet as the input file because this Microsoft page gives the correct info for connecting to a spreadsheet.  I'd rather connect to a csv file, to be honest, but needs must.


  • Add a TestContext into the TestClass 
The document doesn't describe what a TestContext is, or why, but you need one.  The sample text shows a private field with a public member that implements getters and setters.  You'll refer to the private field in tests so it's handy to be able to name it (with a short name).  I'd guess it's used to keep track of what row you're on in the spreadsheet.
  • Decorate your Test Method
A couple of decorators are all you need - though again I'm not clear what they each do.
[DeploymentItem("TestProjectFolder\\InputFile.xlsx")]
[DataSource("UseTheNameAttributeFromTheAddElementInDataSourcesInAppConfig")]


  • Import System.Data
I'd to add a reference to System.Data and pop a using statement at the top of my TestHarness.cs file.
  • Write your test.
Data is imported from your spreadsheet as an object, and it seems to need you to hard code the column name.
         //Arrange
            string MPString = context.DataRow["MP"].ToString();
            if (!(String.IsNullOrEmpty(MPString)))
            {
                mp = Int32.Parse(MPString);
            }
 
            string idPrefix = context.DataRow["Prefix"].ToString();

Invoke the DataRow method of the TestContext to get the current row of your input file.  The ToString() method is available which is useful.

As you can see above, to get an int you first call the ToString method and then parse it into an int.  As I may not have any value in that column in the input spreadsheet I have to perform a check first.

You can read the expected result in from this spreadsheet too.

The Act part of the test is to call your web service, passing in whatever input parameters you require.
            //Act
            string actualResult = client.GetData(mp, idPrefix);
 
            //Assert
            Assert.AreEqual(expected, actualPrefix);

I'm using Assert.AreEqual but I find if a row fails that the only clue I get from the output is "(Data Row x)" where the first test is Row 0 (the heading row is ignored in the counting).  Perhaps a different Assert method that lets me output what the expected result or some input was would help.  For now I've added a column of numbers into my test input file as a guide.


Useful Note

I've also found that storing the test input file in my test project's folder means I can add it into the solution easily.  Then when I want to edit the input file I just double click on it in solution explorer and it launches Excel.

Summary

Add a service reference to your existing WCF service.
Import System.Data and include it in your test class file
Add a TestContext member into the test class
Use TestInitialize and TestCleanup to ensure you instantiate the service and close it properly at the end of a test.
Add a custom section into your app.config file in the test project's folder
Write your tests, with two additional decorators.  Use TestContext.DataRow to read a value from a column into a variable.

Saturday, 15 August 2015

Asynchronous Programming

Old async programming with callbacks/delegates/promises

Synchronous programming blocks the main thread, which in web apps typically results in the UI blocking and being unresponsive while some backend processing occurs.

Asynchronous programming (such as C#'s Task<T> or javascript's promises) implement non-blocking asynchronous programming that frees up the UI to remain responsive by allowing the slow back end processing to occur in parallel (on another thread) and once it has completed proceeding with the program.

Historically this was achieved by the use of callbacks to signal the completion of the background operation.  If you begin to execute a long running process you invoked it with as an input parameter a callback function / pointer-to-function / delegate that would be signalled (execution would jump to) on completion of the long running process.   If program calls a long-running operation a you might pass in a delegate/the address of method b.  When the operation a completes your program resumes in method b.  If method b calls an async call to a long running process it may invoke it with a delegate of method c.  It can quickly become confusing and hard to keep track of the program execution flow.

C# 5 New model

C#5 handles much of this behind the scenes,  New asynchronous methods turn your code into a callback state machine that tracks and handles the program flow for you.

Mark your method with a new "async" modifier
Return void or Task<T> (where T is the type you would have returned normally)
Use the await operator to yield control, i.e. await <methodname>  where methodname is an asynchronous method.
Program flow resumes - in the same method -  after the awaited method has completed - but in the mean time your UI has been responsive as normal.  Thus your code looks and fields like good old synchronous code, even through it is executing asynchronously.

        public Form1()
        {
            InitializeComponent();
            ComputeStuffAsync();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
        }

        async void ComputeStuffAsync()
        {
            var sum = 0.0;

            await Task.Run(() =>
            {
                for (var i = 0; i < 200000000; i++)
                {
                    sum += Math.Sqrt(i);
                }
            } );
            lblSum.Text = sum.ToString();
            lblSumTxt.Text = "Once";

            await Task.Run(() =>
            {
                for (var i = 0; i < 200000000; i++)
                {
                    sum += Math.Sqrt(i);
                }
            });
            lblSum.Text = sum.ToString();
            lblSumTxt.Text = "Twice";
        }

Friday, 14 August 2015

Starting LINQ

Language Integrated Query was introduced in C# 3.0 and it allows you to query any collection - in memory, a database, etc with standard powerful logic / operators.  Historically developers had to learn multiple APIs to deal with data from different sources e.g. XML, database or in memory.  LINQ brings data access into the .Net languages (that support generics, specifically support IEnumerable<T>) and provides both intellisense and static type checking within the IDE.  These were lacking in previous data access coding APIs.   This one common way of accessing data (LINQ) is akin to the one common way of accessing external communications (WCF) which unified calls queues, web services, pipes, etc.

Out of the box LINQ provides approximately 50 standard query operators:-

  • Filtering (e.g. where)
  • Projection (e.g. select. Projection returns just some data attributes in an object/table, not all)
  • Joining
  • Partitioning (skip, take.  Useful for pagination e.g. give me results 11-20).
  • Ordering (order by)
  • Aggregating (group by)
Many of these are similar to SQL.

The same standard operators work everywhere.  There are additionally custom query operators / providers produced by the user community (e.g. LINQ to Amazon).

  • LINQ to SQL supports SQL Server only.  LINQ to entities provides ORM features.
  • LINQ to XML supports XML, with a new XML API (System.XML.Linq) that is less formal and easier to use.
  • LINQ to Objects supports working with objects in memory.  This is often overlooked but is very powerful, and can replace foreach loops and selections with much more succinct code.


You can return results as collections of anonymous classes.  There are two styles/syntaxes for writing LINQ queries, Method Syntax and Query Syntax.

Method Syntax

(Very like SQL, just with the select statement at the end of the expression)
var results = from x in staff where x.Grade = "Manager"
select new {x.Name, x.PhoneNumber}

Query Syntax


(Uses a lambda expression - input parameter(s) to an anonymous method that returns a result).
var results = staff.Where(x=>x.Grade=="Manager");


LINQ Query Operators

LINQ contains some familiar and some new (but very useful) operators:

orderby

This is the same as the SQL order by clause.

            var doubleQuery = from method in typeof(double).GetMethods()
                        orderby method.Name
                        group method by method.Name into groups
                        select new { MethodName = groups.Key, NumberOfOverLoads = groups.Count() };

            foreach (var item in doubleQuery)
            {
                Console.WriteLine(item);
            }
            Console.ReadLine();

group

Same as the SQL group by clause.  (See orderby example, above).

any

Returns true if a collection has any members.
var largeList = Enumerable.Range(1,20);
var largeListEmpty = largeList.Any();
Console.WriteLine("largeList contains items? " + largeListEmpty);

contains

Returns true if a collection contains the item(s) provided in the statement
Console.WriteLine("largeList contains 7? " + largeList.Contains(7));
Console.WriteLine("largeList contains 27? " + largeList.Contains(27));

take

Takes (copies) the first n items out of the collection.
var largeList = Enumerable.Range(1,20);
var smallList = largeList.Take(5).Select(x => x * 10);

foreach (var item in smallList)
{
    Console.WriteLine(item);
}


foreach (var item in largeList)
{
    Console.WriteLine(item);
} //largeList is unchanged as the items were copied out.

Take can be a useful way of limiting your result set.

zip

Zips together two collections (presumably they need to have a matching number of items).
string[] shortMonth = { "Jan", "Feb", "Mar", "Apr", "May" };
string[] longMonth = { "January", "February", "March", "April", "May" };

var monthMapping = shortMonth.Zip(longMonth, (sMonth, lMonth) => sMonth + ": " + lMonth);

foreach (var m in monthMapping)
{
     Console.WriteLine(m);
}
Console.ReadLine();

Deferred Execution

LINQ query expressions usually do not execute until we access the result, i.e. they are lazy operators.  (Certain LINQ operators such as count are greedy and execute immediately).  Thus you can build up queries as user input changes, and only execute it once, when needed.  In the order by example, above, the LINQ query only executes when the foreach loop calls it.  It is defined first but execution is deferred until needed.  This is not unlike deploying a stored procedure in a database that only executes when called.

Summary

LINQ allows you to query any collection using one standard API
LINQ standard operators work against IEnumerable<T>
It has many useful operators
It has a powerful chaining syntax to combine operators together powerfully.