One of the essential parts of integrating unit testing successfully into the organization is to follow up on developers as they learn to use the techniques of unit testing. Doing test reviews (vs. code reviews) can have many benefits.
In this article I'll talk about what the benefits of test reviews are, and provide a basic guideline of things to look for when reviewing someone's tests.
there are three main areas to watch out for: readability, maintinability and testability
We want to make sure the test is as readable as possible to whoever is looking at it, even if it is the first time they read this test. that means we want to surprise the reader as little as possible, as well as make sure that the intent of the test as well as what the test is actualy doing or any assumptions it may have, are clearly visible.
for example, the test name could be:
[Test]
public void IsLoginOK_NonExistingUserName_ReturnsFalse()
Make sure that in the test class, if a [Setup] method is used, it only initialized objects that are used by all the tests in that class. otherwise it gets harder to understand the dependencies that each test needs. Short example:
Calculator c;
[Setup]
public void Setup()
{
c = new Calculator; //assumed to be used by all the tests in this class
}
If there are some objects that only some tests need, but you still want to make sure they are initialized in one place, create a special factory method that creates those dependencies and call it directly from only those tests that need that object.
for example:
[Test]public void IsLoginOK_WithInvalidUserObject_ReturnsFalse()
{
UserObject user = CreateUserWithBadLogin();
}
[Test]
public void IsLoginOK_WithInvalidUserObjectAndNoDB_ThrowsException()
{
UserObject user-CreateUserWithBadLogin();
}
public UserObject CreateUserWithBadLogin()
{
return new user ('bad login');
}
[Test]
public void IsLoginOK_WithInvalidUserObjectAndNoDB_ThrowsException()
{
string loginStringWithTooManyCharacters = "123456789";
...
}
[Test]
public void IsLoginOK_WithInvalidUserObjectAndNoDB_ThrowsException()
{
//if I only look at the test I will have no idea the logger will always return 'false' when "Write" is called.
ILogger stubLogger = new MyLogger();
...
}
//the stub
class MyLogger:ILogger
{
public bool Write(string text)
{
return false;
}
}
here is a more readable version of this:
[Test]
public void IsLoginOK_WithInvalidUserObjectAndNoDB_ThrowsException()
{
ILogger stubLogger = new MyLogger();
stubbLogger.WriteReturnValue=false; //test has full and explicit control of stub behavior
...
}
//the stub
class MyLogger:ILogger
{
public bool WriteReturnValue;
public bool Write(string text)
{
return WriteReturnValue;
}
}
maintinability problems mean that maintinaing your tests takes too long. sometimes longer than the time the tests save you on the project.
[Test]
public void Calculate_TwoNumbers_Subtracted_1()
{
bool expected = 1;
Calculate_Verify(2,1,expected);
}
[Test]
public void Calculate_TwoNumbers_Subtracted_1()
{
bool expected = 3;
Calculate_Verify(2,5,expected);
}
private void Calculate_Verify(int howmuch, int from,int expected)
{
int result = calc.Calculate(howmuch,from);
Assert.AreEqual(expected,result);
}
there are several smells of over specification in mocks and stubs. usually specification means that you are assuming too much about the underlying implementation of the code under test, to a point where any little change to private code may break your test without there actually being a bug.
nowGoogle.com adalah Multiple Search Engine Popular|intermezo