Category Archives: Code

Software Development

Code Kata One as Code – Supermarket Pricing

The code kata on supermarket pricing is one we wanted to do because we have some interest in pricing rules. However, it’s written as a design exercise (which is a good thing), whereas we still wanted to do some coding.
So :

The Checkout Pricing Kata

Some things in supermarkets have simple prices: this can of beans costs £0.20. Other things have more complex prices. For example:
• three for a £ (so what’s the price if I buy 4, or 5?)
• £1.99/pound (so what does 4 ounces cost?)
• buy two, get one free (so does the third item have a price?)
Here’s an example stock list with pricing and rules

Stock Pricing
Baked Beans: 20p per can, with a three-for-two offer.
Bananas: £1 per Kg
Bagged Bananas: £1.20 per bag
Beer: £1.50 per bottle, with a three-for-£4 offer
Bagels: £3 per dozen or £2.00 per half-dozen or 50p each
Kitchen Roll: 50p each
Beer ‘n’ Beans Cleanup Offer: Buy 3 cans of beans, 3 bottles of beer and get one free kitchen roll (not combinable with any other offer).
Beans ‘n’ Bagel Breakfast Offer: Get 6 cans of beans and a dozen bagels for £3.50 (not combinable with any other offer).

Checkout Pricing

Write something which, given a list of items purchased, will print out a priced and itemised receipt, with weights shown where relevant and all discount rules correctly applied. The customer should not be able to get a better price by re-organising or splitting up the shopping basket. The receipt should help the uncertain customer to see this.
In TDD style, do it by writing code to pass tests for a list of increasingly complex requirements.

Example shopping baskets

• 1 can of beans, and 1 bottle of beer
• 6 can of beans, and 3 bottles of beer
• 5 cans of beans and 1.4 kg of loose bananas
• 3kg of bananas and 7 bagels
• 4 cans of beans, 3 bottles of beer and a kitchen roll
• 10 cans of beans, 15 bagels, 4 bottles of beer, 2 kitchen rolls, 3.5 kg loose plus 1 bag of bananas.

I leave to the retail stategists amongst you the question, “Should it always be impossible for the customer to get a cheaper price by adding something to their basket?”

NUnit Constraints Example – a Simple Custom Constraint

Are you short of an NUnit Assertion? You have some code for a test, but you really want it in NUnit constraint form so you can use it like any other test. They are easy to write. Here’s an example which wraps a function you already wrote as a Constraint:

public class EqualsByValueConstraint : Constraint
{
	private readonly object expected;
	private CompareResult compareResult;

	public EqualsByValueConstraint(object expected)
	{
		this.expected = expected;
	}

	public override bool Matches(object actual)
	{
		this.actual = actual;
		compareResult = EqualsByValueOrFailureReason(actual, expected);
		return compareResult;
	}

	public override void WriteDescriptionTo(MessageWriter writer)
	{
		writer.WriteExpectedValue(this.expected);
	}
	public override void WriteActualValueTo(MessageWriter writer)
	{
		base.WriteActualValueTo(writer);
		writer.WriteLine();
		writer.WriteMessageLine("Compare Result " + compareResult);
	}
}
public class CompareResult
{
	public bool IsPass {get;set;}
	public string FailureDescription {get; set;}
}

If your function is just a boolean, then you could remove the CompareResult class. The drawback being that your failure message will only say ‘failed’ rather than give an explanation of the failure. In that case, you might just as well not use the constraint and use the Assert.That(bool, message) overload.

A Very Small Editable PDF for Testing

A Small PDF

Ever wanted a small PDF file, or to tweak your own PDF for testing? Below is a very small PDF which you can paste into a text editor and save as MySmallPdf.PDF.
Two things are easy to edit:

  • The page size. Look for the line /MediaBox [0 0 612 144]. Leave the first (0,0) pair and edit the (612,144) to be (width of page,height of page) in 1/72ths of an inch.
  • One line of text. Look for the line (This is a small text editable pdf) Tj and replace the text with your own.

This is particularly helpful if you are testing http://itextpdf.com/ or itextsharp or some other PDF generator or API, and you want a couple of small identifiable test files to play with.

The Editable PDF

%PDF-1.4
1 0 obj
<< /Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
>>
endobj
2 0 obj
<< /Type /Outlines
/Count 0
>>
endobj
3 0 obj
<< /Type /Pages
/Kids [4 0 R]
/Count 1
>>
endobj
4 0 obj
<< /Type /Page
/Parent 3 0 R
/MediaBox [0 0 612 144]
/Contents 5 0 R
/Resources << /ProcSet 6 0 R
/Font << /F1 7 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 73 >>
stream
BT
/F1 24 Tf
100 100 Td
(This is a small text editable pdf) Tj
ET
endstream
endobj
6 0 obj
[/PDF /Text]
endobj
7 0 obj
<< /Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /MacRomanEncoding
>>
endobj
xref
0 8
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
0000000364 00000 n
0000000466 00000 n
0000000496 00000 n
trailer
<< /Size 8
/Root 1 0 R
>>
startxref
625
%%EOF

The PDF ISO32000 standard

The PDF reference is available for free from Adobe at http://www.adobe.com/content/dotcom/en/devnet/pdf/pdf_reference.html The one you want is the copy of the ISO reference at http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf

Sending large byte[] of binary data through WCF – a simple approach

You can send large streams of data through WCF in two ways: by streaming or by buffer. How to enable streaming is discussed here but has the significant restriction that if you stream, you can only have one (yes, 1) parameter into and out of the service. If your goal is just to pass largish objects such as a spreadsheet or a PDF as part of a service operation this could be a significant hurdle to code around.

“By buffer” means that your large data can be handled with no special treatment at all: it is sent, read into memory (the buffer), and processed just like small messages are. You must understand that buffering means the whole message is buffered; As of early 21st century, that fine on most servers for muliti-megabyte data, but not fine for gigabytes of data.

The simple way to handles megabyte messages is to create a binding Configuration with 2 or 3 parameters increased:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="basicHttpFor2MBMessage" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
          <readerQuotas maxArrayLength="2097000" />
        </binding>
      </basicHttpBinding>
    </bindings>

and have your service endpoint use it:

<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpFor2MBMessage" contract="yourContractName>

Voila. You can now send a 2MB large array through SOAP to WCF.

If your large array is binary data, you declare it in your service classes as byte[], which is why you need the maxArrayLength setting. If you are creating test messages by hand or in a testing tool, you also need to know how to represent binary data in a SOAP message.
The usual answer is, use base64 encoding and it should just work, thus:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://MyServiceName">
   <soapenv:Header/>
   <soapenv:Body>
      <dat:Save>
         <dat:Id>111</dat:applicantId>
         <dat:Pdf>JVBE ... <i>base64 encoded string</i> .... JUVPRgo=</dat:contractPdf>
      </dat:Save>
   </soapenv:Body>
</soapenv:Envelope>

Caveats

Security

The WCF default small buffer and message sizes are a guard against DoS attacks so if your service is publicly visible this would leave it less well guarded.

Performance

How fast does your service process large requests?

If (Expected Peak Requests Per Minute) * (Seconds to Process a Request) is bigger than 60 (Seconds in a Minute) then you need more horsepower.

How much memory do you have?

If (Size of Message * Requests per Hour) – (Speed at which WCF frees up an hour’s worth of used buffers) is bigger than your available memory then you’ll fall over. Alas there is no simple setting for ‘Speed at which WCF frees up an hour’s worth of used buffers’ so that calculation is a problem for another blog post. If you might have a problem, you can use PerfMon to watch memory behaviour during a stress test.

dotCover config file for command line NUnit test coverage

So you want to produce a coverage report for your .Net project, preferably from the command line? If you use dotCover and NUnit then this:

<?xml version="1.0" encoding="utf-8"?>
<AnalyseParams>
    <Executable><!-- Path to your NUnit bin directory e.g.  -->C:\Program Files\NUnit 2.5.10\bin\net-2.0\nunit-console.exe</Executable>
    <WorkingDir><!-- This path works for running dotCover with a config file in the project directory-->bin\Debug\</WorkingDir>
    <Arguments><!-- The dlls containing NUnit tests. Space delimited if more than one-->My.Tests.dll My.MoreTests.dll</Arguments>
    <Output><!-- Path to where I want the report. Can be relative or absolute -->My.Tests.Coverage.html</Output>
    <Filters>
        <IncludeFilters>
            <FilterEntry><!--  _ "Module" means project _ --><ModuleMask>*</ModuleMask></FilterEntry>
        </IncludeFilters>
        <ExcludeFilters>
            <FilterEntry><!--  _ "Module" means project _ --><ModuleMask>My.Tests</ModuleMask></FilterEntry>
            <FilterEntry><!-- namespaces can be filter with a ClassMask with * wildcard --><ClassMask>Namespaces.For.AutogeneratedCode.*</ClassMask></FilterEntry>
            <FilterEntry><ClassMask>SomeUntestable.Class</ClassMask></FilterEntry>
        </ExcludeFilters>
    </Filters>
    <ReportType>html</ReportType>
 </AnalyseParams>

will allow you, from the command line, to type:

dotCover analyse MyConfigFileName.xml

and generate coverage reports. Assuming that dotCover is in your path of course.
I like to set the filters to exclude coverge report on the test project itself as well as autogenerated code.

Covering Multiple Test Projects In One Run

  • Set your working directory to be a parent of all the test projects, e.g. the solution directory.
  • List the full relative paths to each Test dll, space limited:
    <WorkingDir>.</WorkingDir>
    <Arguments>Web.Tests\bin\Debug\MyProject.Web.Tests.dll Implementation.Tests\bin\Debug\MyProject.Implementation.Tests.dll</Arguments>

Filtering and more advanced coverage configs

  • Look down the right hand side of the page here : http://www.jetbrains.com/dotcover/documentation/index.html for documentation, such as it is.
  • Filtering is covered here: http://blogs.jetbrains.com/dotnet/2010/07/filtering-with-dotcover/
  • More complex stuff is touched on here: http://blogs.jetbrains.com/dotnet/tag/code-coverage/