Showing posts with label property based testing. Show all posts
Showing posts with label property based testing. Show all posts

Sunday, September 20, 2015

The Cloud-Capped Towers OR AutoFixture

"The cloud-capped towers, the gorgeous palaces,
The solemn temples, the great globe itself,
Yea, all which it inherit, shall dissolve,
And, like this insubstantial pageant faded,

Leave not a rack behind. We are such stuff
"
-- Shakespeare, The Tempest
Act IV, Scene I, Lines 152 -156

In my day-to-day work I do a lot of .Net programming.  It seem at some point in each of the applications I am either enhancing or creating I ended including Mark Seemann's AutoFixture (if it is not already in use).  AutoFixture is an easy way to create a fixture object.  A fixture object is an object which centralizes your helper methods in your test code, like methods which create your system under test and help generate test data.

Fixture objects are great and I often find myself wanting one in my day-to-day work, but I am lazy.  Since I am lazy I do not want to go to all the trouble of creating my own fixture object, to quote Homer Simpson, "Can't someone else do it".  Luckily in the .Net realm someone already has, Mark Seemann.  AutoFixture lets you get the best of all worlds, you get a fixture object and you do not have to write the framework around it!  (working with it for a few years now, I can say it is well thought out and not a big hair ball, see also Simple Made Easy for the full reference)

How about some examples?  (taken from the AutoFixture cheat sheet and rewritten using xUnit)



We see in the above lots of wonderful things.
  • We can walk up to the fixture object and ask it for some test data.  
  • We can use the AutoData attribute and ask for test data.  
  • We can register implementation for abstract types.  
  • We can create collections of test data.
  • We can build specific test data saying what attributes we care about and letting the fixture object set up the rest.
  • We can even have a do method to allow for modification outside of the object we are having the fixture object create (this is not good design but sometimes it is needed).
As I work more with AutoFixture I find more and more uses for it.

Another framework I use a lot in my day-to-day .Net programming is Moq.  Guess what, AutoFixture can be uses as an auto-mocking container with Moq (and it has plugins for other mocking frameworks too).

Yet another example.  (using MS Test taken from an overview of AutoFixture I did at work recently)



We see in this example that we had a simple class called Echo which got top hatted into having logging and a backup added to it.  The interactions with the logger and back-upper need to be tested, luckily we can tell the fixture object that we would like to get spy objects for the logger and back-upper.  These spies from AutoFixture are Moq mocks which allows us to verify that the behaviors we want.

By using AutoFixture and Moq we can meet all the "needs" of Top Hats everywhere.

(The term Top Hats comes from Uncle Bob's Clean Coder series episode 7, in which there is a scene with an Architect talking about choosing an IDE and Database for a project hence the term Top Hat and top hatting to describe this type of "architecture".)

I find that AutoFixture allows me to simplify my test code (simple as discussed in Simple Made Easy) and allows me to stay focus on what I am actually trying to test.

Saturday, July 5, 2014

I Have No Freaking Clue What I Am Doing... OR Saving Throws with Property Testing

"What majesty should be, what duty is,
Why day is day, night night, and time is time,
Were nothing but to waste night, day, and time.
Therefore, since brevity is the soul of wit,
"
-- Shakespeare, Hamlet
Act II, Scene II, Lines 87-90

I'll admit it, sometimes I have no freaking clue what I am doing.  Much like the internet dog meme, I feel completely out of my league.  You have to start somewhere and no clue is often the first stop on the journey to mastery.

"A journey of a thousand leagues started with what was under one footstep."
-- Tao Te Ching verse 64, translated by Jan J. L. Duyvendak

Property Testing allows one to run their code under test through it's paces.  Let us take a look at using Property Testing against FizzBuzz and see what we can learn.


We see that we have a fairly simple implementation of FizzBuzz.

public string Translate(int value)
{
var result = string.Empty;
if (value % 3 == 0) result += "Fizz";
if (value % 5 == 0) result += "Buzz";
return string.IsNullOrEmpty(result) ? value.ToString() : result;
}

For our first test case we use the Test Case property of NUnit to show what the results of the Translate on the FizzBuzzer would be for different inputs.  Note, I am showing the result here after many rounds of Red, Green, Refactor.  I cannot predict the future and as such I had two different test methods for 2 and 3 and ended up refactoring them to the "one" you see below, but I digress.

[TestCase(2, Result = "2")]
[TestCase(3, Result = "Fizz")]
[TestCase(5, Result = "Buzz")]
[TestCase(15, Result = "FizzBuzz")]
public string Given_Value_It_Must_Return_The_Given_Result(int value)
{
return _fizzBuzzer.Translate(value);
}

This is great, but what happens for other values?  How do we know if this really works?

[Test]
public void Given_A_Number_Not_Divisible_By_3_Or_5_It_Must_Return_That_Number()
{
var value =
from number in Any.OfType<int>()
where number%3 != 0 && number%5 != 0
select number;
Spec.For(value, v => _fizzBuzzer.Translate(v).Equals(v.ToString()))
.QuickCheckThrowOnFailure();
}

We use the Property Test above using fscheck to show that any number not divisible by 3 or 5 will return the ToString value of the number.  We do not have to check 15 since 3 * 5 =15 and therefore it is covered by the Fundamental Theory of Arithmetic.

private static Gen<int> DivisibleBy(int divisor)
{
var divisibleBy =
from number in Any.OfType<int>()
where number % divisor == 0
select number;
return divisibleBy;
}
[TestCase(3, "Fizz")]
[TestCase(5, "Buzz")]
[TestCase(15, "FizzBuzz")]
public void Given_A_Number_Divisible_By_Divisor_It_Must_Contain_Expected(
int divisor, string expected)
{
Spec.For(DivisibleBy(divisor), d => _fizzBuzzer.Translate(d).Contains(expected))
.QuickCheckThrowOnFailure();
}

Next we test that every number divisible by 3 contains the string "Fizz", likewise we do the same with 5 and "Buzz" and 15 with "FizzBuzz".  We check that they contain the string, so that if we get a value like 45, which is 3 * 15, for our divisible by 3 value we do not have a failing test because we got "FizzBuzz" back instead of just "Fizz", this is a very important thing to think about with Property Testing.  Note also, this is another case were refactoring played a big part in the final result.  I did not start off with a DivisibleBy function; no I found that the generate code for the 3 and 5 looked a lot a liked, so I combined them into the function you now see.

[Test]
public void Given_A_Number_It_Must_Return_Fizz_Buzz_FizzBuzz_Or_A_Number()
{
Spec.ForAny<int>(x => true)
.Classify(x => _fizzBuzzer.Translate(x).Equals("Fizz"), "Fizz")
.Classify(x => _fizzBuzzer.Translate(x).Equals("Buzz"), "Buzz")
.Classify(x => _fizzBuzzer.Translate(x).Equals("FizzBuzz"), "FizzBuzz")
.Classify(x => Regex.IsMatch(_fizzBuzzer.Translate(x), @"\d+"), "number")
.QuickCheckThrowOnFailure();
}

To show that the generator was in fact covering all four different possibilities I set up a "test" which was using fscheck's classification to show the break down of the different values which were coming out of Translate.

[Test]
public void Given_A_Number_Divisible_By_3_And_5_It_Must_Contain_Both_Fizz_And_Buzz()
{
Spec.For(DivisibleBy(3*5), d => string.IsNullOrEmpty(_fizzBuzzer.Translate(d)) == false)
.And(d => _fizzBuzzer.Translate(d).Contains("Fizz"))
.And(d => _fizzBuzzer.Translate(d).Contains("Buzz"))
.QuickCheckThrowOnFailure();
}

Last I set up a test case to show that if a value was divisible by both 3 and 5 it will contain both "Fizz" and "Buzz".  Now this test case was not needed since it was covered above, but I wanted to show how the And works.

There you have it FizzBuzz using Property Testing.  I found the examples in fscheck's GitHub repo very helpful.

Note, I used QuickCheckThrownOnFailure to cause the unit test to actually fail the test runner when the property is not true for some value.  This is very important to do if you are using something like NCrunch to run your tests.  If you have a property which fails for some value and do not use QuickCheckThrownOnFailure on your tests it will "pass" from the runner's point of view, but the result will give the value which falsifies it, this was not what I wanted so I had fscheck throw an exception when the property was falsified.

Sunday, June 1, 2014

Advance Unit Testing with NUnit OR How to do Property Based Testing in C# Without Using F#

"You do advance your cunning more and more."
-- Shakespeare, A Midsummer's Night Dream
Act III, Scene II, Line 128

Intro


Sir you got F# in my C#.  I do not wish to add F# to my Solution just to be able to test my code.  Is there a way to get similar functionality to FsCheck without using F#?

Glad you asked.  I believe NUnit can assist us here.

FizzBuzz with NUnit




First thing we see is a very uninteresting version of FizzBuzz.

public string FizzBuzz(int value)
{
if(value < 0) throw new ArgumentException("Value must be positive.");
var ret = string.Empty;
if (value%3 == 0) ret += "Fizz";
if (value%5 == 0) ret += "Buzz";
return string.IsNullOrEmpty(ret) ? value.ToString() : ret;
}

Nothing really interesting going on here other than using a variable to preserve state so that we do not have to check for 15 or have more than one return statement.

Excepted Exception


[Test, ExpectedException(typeof (ArgumentException))]
public void Negative_Values_Throws_An_ArgumentException()
{
FizzBuzz(-1);
}

We see that we can declare that an exception will be thrown and thus have test coverage for our exception cases.

If we want to make sure that every detail of our exception matches what we think it should be NUnit offers a more verbose check too.

[Test,
ExpectedException(typeof (ArgumentException), ExpectedMessage = "Value must be positive.",
MatchType = MessageMatch.Exact)]
public void Given_A_Negative_1_It_Will_Throw_An_ArgumentException_With_The_Message_Of_ValueMustBePostive()
{
FizzBuzz(-1);
Assert.Fail("Should have thrown an execpetion");
}

Ranges of Values in One Test Case


[Test]
public void Generate_A_Range_Of_Fizz_Data(
[Range(3, 300, 3)] int value)
{
var removeBuzz = (value % 5 == 0) ? 3 : value;
Assert.That(FizzBuzz(removeBuzz), Is.EqualTo("Fizz"));
}

If we want to we can define a range of values to check.  With the example above we see that we are checking the values: 3, 6, 9, ..., 300 are not divisible by 5 (thus, 15, 30, 45, ... will not be checked).  This data will be used to verify that Fizz is returned for each of these test cases.  We can do a similar thing with Excepted Exceptions.

[Test, ExpectedException(typeof (ArgumentException))]
public void Generate_A_Range_Of_Invali_Fizz_Data(
[Range(-1000, -1, 1)] int value)
{
FizzBuzz(value);
Assert.Fail("Should have thrown an exception");
}

Test Case


We can set up a test case using the TestCase attribute.

[TestCase( 0, "FizzBuzz")]
[TestCase( 1, "1")]
[TestCase( 2, "2")]
[TestCase( 3, "Fizz")]
[TestCase( 4, "4")]
[TestCase( 5, "Buzz")]
[TestCase( 6, "Fizz")]
[TestCase(10, "Buzz")]
[TestCase(15, "FizzBuzz")]
[TestCase(45, "FizzBuzz")]
[TestCase(-1, "error", ExpectedException = typeof(ArgumentException))]
public void FizzBuzz_Test_Cases(int value, string expected)
{
Assert.That(FizzBuzz(value), Is.EqualTo(expected));
}

This allows us to reuse the boilerplate test case setup while allowing us to provide the test data.  In this case we are providing both the value to test and the expected result.

We can be more explicit with the result and use the Result property of the TestCase attribute.

[TestCase( 0, Result = "FizzBuzz")]
[TestCase( 1, Result = "1")]
[TestCase( 2, Result = "2")]
[TestCase( 3, Result = "Fizz")]
[TestCase( 4, Result = "4")]
[TestCase( 5, Result = "Buzz")]
[TestCase( 6, Result = "Fizz")]
[TestCase(10, Result = "Buzz")]
[TestCase(15, Result = "FizzBuzz")]
[TestCase(45, Result = "FizzBuzz")]
[TestCase(-1, ExpectedException = typeof(ArgumentException))]
public string FizzBuzz_Test_Cases_With_Expected_Results(int value)
{
return FizzBuzz(value);
}

Note, when testing this way you do not call Assert but instead return the value (note also the return type of the test function is a string in this case and not a void).  NUnit will assert the result of method for you!

Generating Test Data


Property Based Testing is a very a powerful idea which decouples the behavior which you are testing from the generating of test data.  I believe an example would be good about now.

// Random does not work with NCrunch unless NUnit is set to UseStaticAnalysis
[Test]
public void Generate_Buzz_Data(
[Random(1, 10000, 100)] int value)
{
var removeFizz = (value % 3 == 0) ? 5 : value * 5;
Assert.That(FizzBuzz(removeFizz), Is.EqualTo("Buzz"));
}

We see above the use of the Random attribute.  Random will generate a value between 1 and 1000 (the first two arguments that we pass it), in this case, this will be done 100 times!  (100 is the third argument that we pass it.)  We see also that for this test we want to verify the Buzz functionality, so we reshape the data in such a way that we always get a value which should produce Buzz.  This kind of testing is a great way to find edge cases.

We see a comment above the test case which means something is going wrong.  In this case the comment is telling use that when we use Random with NCrunch we need to change the Configuration to use UseStaticAnalysis for NUnit.  You can read all about it here.  If you do not change this setting you'll get the following error message.

"This test was not executed during a planned execution run. Ensure your test project is stable and does not contain issues in initialisation/teardown fixtures."

NUnit offers other ways to generate data, one of which is the Datapoints / Theory combo.

[Datapoints] public int[] Values = new[] {-1, 0, 2, 3, 4, 5, 9, 15, 25, 45};
[Theory]
public void Numbers_Divisible_By_15_Will_Return_FizzBuzz(int value)
{
Assume.That(value % 15 == 0);
var actual = FizzBuzz(value);
Assert.That(actual, Is.Not.Null);
Assert.That(actual, Is.EqualTo("FizzBuzz"));
}

The way that Theory works is that it will use the values from the field marked as Datapoints.  In the case above we are restricting the values just to what is divisible by 15, thus we are testing the FizzBuzz functionality.

We can also set up an array of arrays which contain test case values using the TestCaseSource attribute.

public static object[] FizzBuzzTestData =
{
new object[] { 1, "1"},
new object[] { 2, "2"},
new object[] { 3, "Fizz"},
new object[] { 9, "Fizz"},
new object[] { 5, "Buzz"},
new object[] {10, "Buzz"},
new object[] { 0, "FizzBuzz"},
new object[] {15, "FizzBuzz"}
};
[Test, TestCaseSource("FizzBuzzTestData")]
public void FizzBuzz_Test_Data(int value, string expected)
{
Assert.That(FizzBuzz(value), Is.EqualTo(expected));
}

We see with the example above that we are defining both the value and excepted result which are passed into the test.

We can take this a step forward and define an actual test generator class.

public class FizzBuzzTestCaseDataFactory
{
public static IEnumerable<TestCaseData> TestCaseData
{
get
{
yield return new TestCaseData(1).Returns("1");
yield return new TestCaseData(2).Returns("2");
yield return new TestCaseData(3).Returns("Fizz");
yield return new TestCaseData(33).Returns("Fizz");
yield return new TestCaseData(5).Returns("Buzz");
yield return new TestCaseData(55).Returns("Buzz");
yield return new TestCaseData(15).Returns("FizzBuzz");
yield return new TestCaseData(165).Returns("FizzBuzz");
yield return new TestCaseData(-1).Throws(typeof (ArgumentException));
yield return new TestCaseData(-11).Throws(typeof (ArgumentException));
}
}
}
[Test, TestCaseSource(typeof(FizzBuzzTestCaseDataFactory), "TestCaseData")]
public string Data_Factory_Test_Case(int value)
{
return FizzBuzz(value);
}

We see that by using the TestCaseSource attribute and telling it the typeof the test generator class and the name of the method for generating test case data, NUnit will call the method and verify our functionality for us!

We also see that the TestCaseData class allows us to specify the results.  In my opinion this allows for very high levels of readability.

I know what you might be thinking, this test data generating is fine but why use this over a for loop?  Well the for loop would test the same functionality, but it would not show up as different test cases to the test runner (unless you do so real hacking), while the NUnit test data generators would.  With the NUnit test data generators, if one of the values fail the test case you'll see the offending value instead of just seeing that the test case with a for loop broke.

This is what the values for Generate_Buzz_Data (the test using the Random attribute) actually look like to the test runner.

Generate_Buzz_Data

NUnit.CharacterizationTests.Generate_Buzz_Data(5224):



NUnit.CharacterizationTests.Generate_Buzz_Data(8147):



NUnit.CharacterizationTests.Generate_Buzz_Data(8619):


...

As you can see it would be very easy to see why a value would make a test fail using this, the same could not be said for the loop.

Look Mom, No Quickcheck


There you have it advance unit testing with NUnit.  Use NUnit's different test data generators we were able to do Property Based Testing without using quickcheck.

I do want to make a quick call out to Luke Wickstead's excellent posts on NUnit.  Reading this post allowed me to figure out how the TestCaseSource really worked.