Reputation: 5822
OK, I know what a unit test is but I use it in some projects and not others...some clients don't know how its done and follow one convention...blah blah.
so here I am asking, how EXACTLY is a unit test process created? I hear, and read, that you write the tests first then the functionality and write the tests for that functionality and also use code coverage to identify any "slips" of not having tests for that code which has not been covered.
So, lets use a simple example:
Requirement: "application must return the result of 2 numbers combined."
you and I know we would have a class, something like "Addition" and a method "Add" which returns an integer like so:
public class Addition
{
public int Add(int num1, int num2)
{
return num1 + num2;
}
}
But even before writing this class, how do you write tests first? What is your process? What do you do? What would the process be when you have that spec doc and going into development?
Many thanks,
Upvotes: 2
Views: 958
Reputation: 31454
Process you're referring to is called Test-Driven Development. Idea is simple and close to what you described; given functionality, you start writing code by writing test for this functionality. In your add example, before any working code is written you should have a simple test - a test that fails.
[Test]
public void TestAdd()
{
var testedClass = new Addition();
var result = testedClass.Add(1, 2);
Assert.AreEqual(result, 3);
}
This is a simple test for your .Add
method, stating your expectations of the soon-to-be working code. Since you don't have any code just yet, this test will naturally fail (as it is supposed to - which is good).
Next step is to write the most basic code that makes the test pass (naturally, the most basic code is return 3;
but for this simple example this level of details is not necessary):
public int Add(int num1, int num2)
{
return num1 + num2;
}
This works and test passes. What you have at this point, is basic proof that your method works in the way you stated it in your assumptions/expectations (the test).
However, you might notice that this test is not a good one; it tests only one simple input data of many. Not to mention, in some cases one test might not be enough and even though you had initial requirements, testing might reveal more is needed (for example arguments validation or logging). This is the part when you go back to reviewing your requirements and writing tests, which leads us to...
At this point you should refactor code you just wrote. And I'm talking both unit test methods code and tested implementation. Since Add
method is fairly simple and there's not much you can improve in terms of adding two numbers, you can focus on making test better. For example:
Like this:
[TestCase(0, 0, 0)]
[TestCase(1, 2, 3)]
[TestCase(1, 99, 100)]
public void Add_ReturnsSumOfTwoNumbers(int first, int second, int expectedSum)
{
var testedClass = new Addition();
var actualSum = testedClass.Add(first, second);
Assert.That(actualSum, Is.EqualTo(expectedSum));
}
Refactoring is topic worth it's own book (and there are many), so I won't go into details. The process we just went through is often referred to as Red-Green-Refactor (red indicating failing test, green - passing one), and it's part of TDD. Remember to rerun the test one more time in order to make sure refactoring didn't accidentally break anything.
This is how the basic cycle goes. You start with requirements, write failing test for it, write code to make test pass, refactor both code and tests, review requirements, proceed with next task.
Few useful resources that are good natural follow-up once you get to know the idea behind TDD (even from such brief explanation as presented in this post):
Upvotes: 5