Solving the diamond kata with property-based testing series
- How to get started with Property-based Testing in C#
- Input generators in property-based tests with FsCheck
- First and Last line content
- Height equals Width
- Outside space symmetry
- Symmetry around the vertical axis
- Symmetry around the horizontal axis
- No padding for input letter row
- Letters order
All code samples are available on github
Intro
Last time, we discovered some interesting patterns with the diamond's global shape and found out that it's always quadratic. Today, we'll look at the space distribution around the diamond and try to figure out if there's a property hidden there that we could exploit.
Outside space symmetry
If you take each line individually, it seems there's a pattern where the outside space is equal on each side of that diamond line.
e.g.
For input E:
Line A
has four spaces on the left and the right.
Line B
has three spaces on the left and the right.
etc., you get the idea
input: E
----A----
---B-B---
--C---C--
-D-----D-
E-------E
-D-----D-
--C---C--
---B-B---
----A----
C# Tests
[Property(Arbitrary = new[] { typeof(LetterGenerator) })]
public Property SpacesPerRowAreSymmetric(char c)
{
return Diamond.Generate(c).All(row =>
CountLeadingSpaces(row) == CountTrailingSpaces(row)
).ToProperty();
}
private int CountLeadingSpaces(string s)
{
return s.IndexOf(GetCharInRow(s));
}
private int CountTrailingSpaces(string s)
{
var i = s.LastIndexOf(GetCharInRow(s));
return s.Length - i - 1;
}
private static char GetCharInRow(string row)
{
return row.First(x => x != ' ');
}
Here we used some built-in methods of the .NET library, which makes these tests simple to read and short to write. I also created three helper methods; CountLeadingSpaces
, CountTrailingSpaces
, and GetCharInRow
to make it more readable. It almost reads like a sentence.
Diamond.Generate(c)
Generates the diamondAll()
validates the inner condition for each linerow => CountLeadingSpaces(row) == CountTrailingSpaces(row)
validates that the number of spaces are equal on each sideToProperty()
Transforms a boolean expression to a property
If you are wondering what's
[Property(Arbitrary = new[] { typeof(LetterGenerator) })]
it's probably because you missed my previous post
Wrapping up
This test is another excellent addition to our tests suite. Symmetry is a fascinating topic, and it's usually behind many properties. Speaking of which, is there any other symmetry that you can spot on the diamond kata? Let's discover it next time. Until then, don't forget to subscribe.
Solving the diamond kata with property-based testing series
- How to get started with Property-based Testing in C#
- Input generators in property-based tests with FsCheck
- First and Last line content
- Height equals Width
- Outside space symmetry
- Symmetry around the vertical axis
- Symmetry around the horizontal axis
- No padding for input letter row
- Letters order
All code samples are available on github