Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Wednesday, 26 March 2014

Beyond Unit Testing

Problem

Unit testing is, IMHO, the essential bare minimum automated testing that should be employed on any software development project beyond the very simplest CRUD application.  So once you have unit tests in place what is the next step?

My preference is for there to be Business Driven Development (BDD) style user acceptance tests. Ideally these would be specified by, where available, the users themselves with help from the developer.  One problem with this however is that the user will probably be thinking in terms of a user interface - be it a web page, an SMS service, a web service or anything in between.  If you test through a user interface then a lot more work is going to be involved and the tests will be a lot more fragile.

Solution

The best option is to test through an API.  One that will be used by the UI programmer to interact with the system as a whole.  That said, systems rarely stand alone and often interact with other systems and again this makes the testing hard.  Even introducing a database or any other state retaining part of the system can

make the testing harder as it will need to be reset to a known state between each test.  For these dependencies then it is better to mock them out of the tests – ensuring that they will not fail no matter what environment you are running on.

The following diagram illustrates the priority I would assign to each kind of test.  The priority indicates not only how early in the project the tests should be developed but also how many tests I would expect to see in each case and how often you would execute them.

With respect to the number of tests at each priority there is no hard and fast mathematical rule.  However I am inclined to think of it as an exponential decrease in number, for instance 1000 tests at priority 1, 100 at priority 2, 10 at priority 3 and 1 at 4.  Actual numbers will depend on how critical the system is and how much effort you are willing to put in to avoid manual testing.

1 API-Mock Testing

This is your bread and butter testing.  Where unit tests leave off so these take over – you are aiming for really good coverage here. These should be run all the time – either in a continuous testing system or at least before check-in.

2 API-Actual Testing

First stage of integration testing.  You may be less reliant on the actual results of tests against the dependencies and more concerned that the structure of the communication protocol is correct.  How often these are run will count on how difficult it is to get your dependencies reset to a baseline.  Database dependencies should be easier in this respect and so the tests can be run before each check-in.  Dependencies on hard to reset (like a payment gateway) or expensive to replicate for testing (like a telephone exchange) systems may be relegated to only being automatically ran just before user/manual testing.

3 UI-Mock Testing

First stage of UI testing.  You may be just ensuring that the screens flow correctly. There should be no need to test your business services behaviour as such since this is tested by the type 1 tests.  These should be run by your build system.  Generally you wouldn’t want it to break the build if they fail as it may be a small issue or perhaps you are working up to a fully functional system.  Failing tests can either be a warning to manual testers of what to avoid, a cue to the test writers that the test needs updating or a cue to the developers that they got something wrong.  It should never indicate that business logic is wrong as that should be covered by type 1 API-Mock testing.

4 UI-Actual Testing

Full UI integration testing.  Your best bet here is to simply smoke test that everything is configured correctly – something that can be quite challenging if you are using DI or IoC.  At times I have used a single screen for this that simply displays pass/fail indicators for every integration point.  True – this isn’t really a UI test but it is useful in confirming configuration and connectivity and can be used in the live environment.  These tests should be run as part of your deployment testing to each environment.

Conclusion

Once you have good coverage with unit tests or a test driven approach to development then it is time to level up to Business/Domain Driven Development where your tests are closer to what the customer understands and needs.  Although customers often think in terms of user interfaces your tests will be less fragile if you test against a coded application programming interface that will then be used by the user interface to drive the domain logic.  Also mock out your dependencies to ensure quick and reliable test execution.  Write fewer tests against the UI and dependencies which will only be executed as part of the build process or in deployment.

Sources

This is not entirely original thought.  Unfortunately I can’t remember where I first read about this approach.  If I find it or remember I’ll link here.

Technorati Tags: ,,,,

Thursday, 24 June 2010

What is using a port on my machine?

Problem

My service connects to a TCP server over a particular port and when establishing the connection throws the exception: “SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted”.

Diagnosing the Issue

Use netstat at the command line to see what is using the port.

netstat –a
Displays all the ports in use.

netstat –b
Displays all the active connections and the process/exe that is using them

In my case a network error had occurred and I believe my service had left the client open, knew it was dead and so was trying to reconnect – throwing the exception.  Restarting the service resolved the issue but the code will need reviewing.

Monday, 24 May 2010

Removing whitespace from HTML tags

The Problem

This situation occurs when using the .net 2.0 classes to transform XML into HTML with a style sheet the transform (System.Xml.Xsl.XslCompiledTransform).  the output will include whitespace inside of certain HTML tags that may occasionally display within form fields when output.  This can be a pain especially when displaying TextArea elements. In IE the behaviour appeared to change unexpectedly when some other element appeared before the TextArea – such as a dropdown list (select).

The Solution

A solution is to remove the whitespaces from these tags after it has been transformed.

private string CleanUpWhitespaceInTags(string xmlString)
{
return cleanUpWhitespaceInTagsRegEx.Replace(xmlString, cleanUpWhitespaceInTagsReplacement);
}

private static readonly Regex cleanUpWhitespaceInTagsRegEx = new Regex(@"<(?<tagName>[\w-]+)\b(?<attributes>[^>]*)>\s*(?<content>[^<]*?)\s*</\1>");
private const string cleanUpWhitespaceInTagsReplacement = "<${tagName}${attributes}>${content}</${tagName}>";


The above code uses a regular expression to match tags that have no inner xml/html and gets named captures of the tag name, it’s attributes and content (without any surrounding whitespace).



To break it down:

























































< match the opening tag’s starting brace
(?<tagName>[\w-]+) capture any valid tag name (containing one or more word characters or dashes)
\b check that we are at a word boundary
(?<attributes>[^>]*) capture any characters after the tag name and before an end brace as attributes
> match the opening tag’s end brace
\s* match any whitespace on the left of the content
(?<content>[^<]*?) capture any character that isn’t a starting brace but don’t be greedy
\s* match any whitespace on the right of the content
</\1> match the closing tag


Disclaimer: Whether this regex covers all scenarios has not been tested but it works for the situation we encountered.



The replacement string then reconstitutes the tag, attributes and content without the leading or trailing whitespace.



Technorati Tags: ,,

Friday, 14 August 2009

T-SQL Cursor Template

This is a handy cursor template for T-SQL on MS SQL Server:
DECLARE curName CURSOR LOCAL FAST_FORWARD
FOR
select *
from mytablename

DECLARE variables

OPEN curName
WHILE 1=1
BEGIN
FETCH NEXT FROM curName
INTO variables

IF @@fetch_status <> 0
BEGIN
BREAK
END

--do work

END

CLOSE curName
DEALLOCATE curName

Monday, 17 November 2008

Clean Code by Robert C. Martin Review (Ch.1)

I recently bought the new book by one of my favourite software development writers, Robert C. Martin (Uncle Bob). I consider myself an experienced software developer and perhaps should already know how to write "Clean Code". Hopefully this book will give me confirmation that I'm on the right track but also I hope to learn a thing or three.

This book is Java programming orientated but the principles should easily transferred to any other programming language. Since my programming language of choice is C# I decided I'd give the book a review and translation to my way of thinking in C#.

Chapter 1: "Clean Code" is the argument for the existence of a book about writing clean code and why it is important. These arguments are well put and well documented in other literature. In a nutshell, code is read more often than it is written and this is as true on new projects as it is in maintenance tasks.

I have no problem with this, the problem comes in the definition of what "Clean Code" looks like. Uncle Bob saves the day by not claiming that this book is the be all and end all definition of what clean code should be. He simply says that the book represents the current opinion of Uncle Bob and his compatriots. Therefore it is open to your modification and, possibly, improvement.

I like that. It gives me the opportunity to think out how I may apply this to my own work without necessarily getting too dogmatic.

As I read the book I'll post my review and C# translations here.