I'm fairly new to Unit Testing and have the following code:
public class PowerOf
{
public int CalcPowerOf(int @base, int exponent) {
if (@base == 0) { return 0; }
if (exponent == 0) { return 1; }
return @base * CalcPowerOf(@base, exponent - 1);
}
}
The unit test (with xUnit) I wrote for it first was this one, but I'm not quite sure if it's the right approach, or if I should use another pattern? What I wanted to know is whether this is the correct usage for passing multiple sets of data into a "unit test" - as I didn't see any docs or reference examples on xUnit's docs?
[Fact]
public void PowerOfTest() {
foreach(var td in PowerOfTestData()) {
Assert.Equal(expected, CalcPowerOf(@base, exponent));
}
}
public class TestData {
int Base {get;set;}
int Exponent {get;set;}
int ExpectedResult {get;set;}
}
public List<TestData> PowerOfTestData() {
yield return new TestData { Base = 0, Exponent = 0, TestData = 0 };
yield return new TestData { Base = 0, Exponent = 1, TestData = 0 };
yield return new TestData { Base = 2, Exponent = 0, TestData = 1 };
yield return new TestData { Base = 2, Exponent = 1, TestData = 2 };
yield return new TestData { Base = 5, Exponent = 2, TestData = 25 };
}
You'd be better of using a specialised construct in xUnit, called a Theory
, that handles so called "Data Driven Tests".
Decorate your testmethod with the Theory
attribute and then make sure to return a static
"member" with input parameters and the expected result as you already kind of did with the TestData class. See the example below, and ref to the xUnit documentation: "Writing your first theory".
I would thus refactor your code like below. Firstly decorating the test with the attributes Theory
and MemberData
and adding parameters to your test "@base", "exponent" and "expectedResult" - as you had in your TestData
class. xUnit
won't allow you to use the TestData class, it only accepts an IEnumerable<object>
and requires it to be static, but the benefit to a foreach loop construct is that all the tests are ran seperately. And for each run with a specific data set you'll get a green or red flag!
public class PowerOfTests
{
[Theory]
[MemberData(nameof(PowerOfTestData))]
public void PowerOfTest(int @base, int exponent, int expected) {
Assert.Equal(expected, CalcPowerOf(@base, exponent));
}
public static IEnumerable<object[]> PowerOfTestData() {
yield return new object[] { 0, 0, 0 };
yield return new object[] { 0, 1, 0 };
yield return new object[] { 2, 0, 1 };
yield return new object[] { 2, 1, 2 };
yield return new object[] { 2, 2, 4 };
yield return new object[] { 5, 2, 25 };
yield return new object[] { 5, 3, 125 };
yield return new object[] { 5, 4, 625 };
}
}