I have tests like that. Negative unit testing.
Does this test make sense? Is it not better to test only the expected exceptional scenarios?
[Test]
public void Get_Root_Units_By_Non_Existing_TemplateId()
{
// ARRANGE
ITemplateUnitDataProvider provider = new TemplateUnitDataProvider(_connectionString);
int templateId = -1;
// ACT
var units = provider.GetRootUnits(templateId);
// ASSERT
Assert.IsNotNull(units);
Assert.Count(0, units);
}
For me this test makes sense. You are checking that the SUT (Subject Under Test) returns an empty array if it hasn't found any records matching the input parameter.
In my opinion, unit tests are used to check your method's correctness. Handling incorrect input correctly is also something you want to test for.
Unit tests are meant to give you a sense of security about your code, so handling invalid input is certainly something I would test.
One good reason to wite fail test is any unit test is better than no unit test
writing fail test lets you know your system well what it should fail on else you have some other scenario's that you are not aware of
Related
I have the following method in my service layer
public ModuleResponse GetModules(ModuleRequest request)
{
var response = new ModuleResponse(request.RequestId);
try
{
response.Modules = Mapper.ToDataTransferObjects(ModuleDao.GetModules());
return response;
}
catch (Exception ex)
{
Log.Error(ex);
response.Acknowledge = AcknowledgeType.Failure;
response.Message = "An error occured.";
return response;
}
}
And I have a unit test written in xUnit like this:
[Fact]
public void GetModulesTest()
{
//Arrange
var mockModuleDao = Mock.Create<IModuleDao>();
var mockLog = Mock.Create<ILog>();
var mockAuditDao = Mock.Create<IAuditDao>();
var moduleList = new List<ModuleItem>
{
new ModuleItem {Id = 100, Category = "User Accounts", Feature = "Users"},
new ModuleItem {Id = 101, Category = "User Accounts", Feature = "Roles Permissions"}
};
mockModuleDao.Arrange(dao => dao.GetModules()).Returns(moduleList);
IUserManagementService userService = new UserManagementService(mockModuleDao, mockLog, mockAuditDao);
var request = new ModuleRequest().Prepare();
//Act
var actualResponse = userService.GetModules(request);
//Assert
Assert.Equal(AcknowledgeType.Success, actualResponse.Acknowledge);
Assert.Equal(2, actualResponse.Modules.Count);
}
Now I have a whole other bunch of retrieval methods in my code similar to the one above.
Are testing such methods redundant? I mean, they are almost a sure pass test, unless I mess up the logic of my Mapping or something.
Also, when testing retrieval methods, what is it that I should be testing for? In my scenario above, I have 2 assert statements, 1 to check if the response is a success, and the 2nd is to check the count of the list.
Is this sufficient? or how can this be further improved to enhance the value of such a unit test?
As always, whether or not a test like that is valuable depends on your motivation for testing.
Is this piece of code mission-critical?
What is the cost if that code fails?
How easily can you address errors, should they occur?
The higher the cost of failure, the more important it is to test a piece of code.
The GetModules method does at least four things:
It returns the modules from the DAO.
It maps the modules from the DAO into the desired return types.
It returns an error message if something goes wrong.
It logs any errors that may occur.
The GetModulesTest tests a single of these four responsibilities, which means that three other tests are still required to fully cover the GetModules method.
Writing small-grained unit tests are valuable, because it enables you do decompose a complex piece of production code into a set of simple, easy-to-understand unit tests. Sometimes, these unit tests become almost inanely simple, to the point where you'll begin to doubt the value of it, but the value isn't in a single unit test - it's in the accumulation of simple tests, which, together, specify how the entire system ought to work.
Now I have a whole other bunch of retrieval methods in my code similar to the one above.
Really? Don't they feel a little... repetitive?
I think Lilshieste made a very appropriate point, that one intrinsic value of unit tests is that they highlight maintainability issues like this. You might say they make code smells more pungent.
Mark Seemann identified four individual responsibilities for this one method you showed us. The Single Responsibility Principle would dictate that you should only have one.
You could conceivably turn this method (and all its kin) into something more like this:
public ModuleResponse GetModules(ModuleRequest request)
{
return _responder.CreateMappedDtoResponse(
request,
ModuleDao.GetModules,
modules => new ModuleResponse {Modules = modules}));
}
Now, at this point, I think you could make a decent argument against unit-testing this method. You'd pretty much be testing the implementation of this method, rather than its behavior. Your unit test would be testing that you call a given method with given arguments, and that's it!
But even if you decided to be a purist and unit test this, there's really only one unit test that you could conceivably write, as opposed to the four that you would have needed to fully cover this method before. Then you write the appropriate unit tests for the CreateMappedDtoResponse methods (and whatever methods it may delegate parts of its work to), and you've got a DRY, well-tested system with a fraction of the number of tests. And if you change a common responsibility like your exception-logging strategy, you can change it in one place, change one unit test, and be done.
So even if your unit tests never catch a bug for you, being a purist helped you to avoid a maintainability issue that would have forced you to write just as much extra code in the first place, and be likely to re-write just as much code later on. Of course, this only happens if you know to listen to your unit tests and change your design accordingly.
I am trying to test a method called Login that, when the user and password parameters are correct, sets the value of two session variables and three cookies and finally returns true.
I've been reading several posts about unit testing, but somehow that didn't make my case fully clear to me. I know that there should be just a single assert per unit test, although you can use more than one as long as you test a single "logical concept".
Login method is correct only if it sets correctly every session variable and cookie and returns the expected value, so I'm not sure if it would be ok to check all these values at once (that would lead me to use six asserts in the unit test, a bit dirty I think) or if I should check the value of each session variable and cookie separately in different tests.
[TestMethod()]
public void SuccessfulLoginTest()
{
// Arrange.
String username = "foo";
String password = "correct password";
Boolean remember = true;
// Act.
Boolean actual = Login(username, password, remember);
// Assert.
Assert.IsTrue(actual);
Assert.AreEqual("foo", HttpContext.Current.Session["Username"]);
Assert.AreEqual(1, HttpContext.Current.Session["Group"]);
Assert.AreEqual("foo", HttpContext.Current.Response.Cookies["Username"].Value);
Assert.AreEqual("en", HttpContext.Current.Response.Cookies["Lang1"].Value);
Assert.AreEqual("es", HttpContext.Current.Response.Cookies["Lang2"].Value);
}
Looks fine to me too. I'm not sure where you got the notion that there should only be one Assert per unit test. That sounds like an "ivory tower" rule that is just plain silly IMO. If your method sets a bunch of variables given a particular input then you should check all those variables given that input. Writing six different unit tests (and associated setup code) seems incredibly inefficient.
But then I tend to lean towards pragmatism over academic "correctness" when it comes to writing software.
You've already noticed correctly, that the one assert rule concerns conceptual assertions, not bare calls to the Assert methods. A nice and common trick that reduces confusion when one logical assert is composed of many assertions and also makes the test more readable is wrapping the asserts in an utility method. In your case it could look similar to this:
void AssertSessionIsValid(string username, int group, ...)
{
Assert.AreEqual(username, HttpContext.Current.Session["Username"]);
Assert.AreEqual(group, HttpContext.Current.Session["Group"]);
...
}
There are many frameworks that help in increasing readability of your tests, like Shouldly.
I'd suggest to assert everything you care about being 'working' and no more than that. Too few asserts and your test will ignore clearly broken functionality; too many and your test will be brittle and break unnecessarily when some irrelevant detail changes.
Have your conditions matched in a boolean variable and if all are fulfilled, then the boolean variable should return true.
Asset this boolean variable
bool AreAllConditionsFulfilled = condition1 && condtionCheckingSessionVariablesOne && conditionCheckingSessionVariablesTwo
Also I would suggest have individual test cases testing each of the Session Variables and assert if they are correct.
[Test]
public void TestUserNameSessionVariable()
{
//Login Code
Assert.AreEqual("foo", HttpContext.Current.Session["Username"]);
}
I'm writing unit tests for a simple IsBoolean(x) function to test if a value is boolean. There's 16 different values I want to test.
Will I be burnt in hell, or mocked ruthlessly by the .NET programming community (which would be worse?), if I don't break them up into individual unit tests, and run them together as follows:
[TestMethod]
public void IsBoolean_VariousValues_ReturnsCorrectly()
{
//These should all be considered Boolean values
Assert.IsTrue(General.IsBoolean(true));
Assert.IsTrue(General.IsBoolean(false));
Assert.IsTrue(General.IsBoolean("true"));
Assert.IsTrue(General.IsBoolean("false"));
Assert.IsTrue(General.IsBoolean("tRuE"));
Assert.IsTrue(General.IsBoolean("fAlSe"));
Assert.IsTrue(General.IsBoolean(1));
Assert.IsTrue(General.IsBoolean(0));
Assert.IsTrue(General.IsBoolean(-1));
//These should all be considered NOT boolean values
Assert.IsFalse(General.IsBoolean(null));
Assert.IsFalse(General.IsBoolean(""));
Assert.IsFalse(General.IsBoolean("asdf"));
Assert.IsFalse(General.IsBoolean(DateTime.MaxValue));
Assert.IsFalse(General.IsBoolean(2));
Assert.IsFalse(General.IsBoolean(-2));
Assert.IsFalse(General.IsBoolean(int.MaxValue));
}
I ask this because "best practice" I keep reading about would demand I do the following:
[TestMethod]
public void IsBoolean_TrueValue_ReturnsTrue()
{
//Arrange
var value = true;
//Act
var returnValue = General.IsBoolean(value);
//Assert
Assert.IsTrue(returnValue);
}
[TestMethod]
public void IsBoolean_FalseValue_ReturnsTrue()
{
//Arrange
var value = false;
//Act
var returnValue = General.IsBoolean(value);
//Assert
Assert.IsTrue(returnValue);
}
//Fell asleep at this point
For the 50+ functions and 500+ values I'll be testing against this seems like a total waste of time.... but it's best practice!!!!!
-Brendan
I would not worry about it. This sort of thing isn't the point. JB Rainsberger talked about this briefly in his talk Integration Tests are a Scam. He said something like, "If you have never forced yourself to use one assert per test, I recommend you try it for a month. It will give you a new perspective on test, and teach you when it matters to have one assert per test, and when it doesn't". IMO, this falls into the doesn't matter category.
Incidentally, if you use nunit, you can use the TestCaseAttribute, which is a little nicer:
[TestCase(true)]
[TestCase("tRuE")]
[TestCase(false)]
public void IsBoolean_ValidBoolRepresentations_ReturnsTrue(object candidate)
{
Assert.That(BooleanService.IsBoolean(candidate), Is.True);
}
[TestCase("-3.14")]
[TestCase("something else")]
[TestCase(7)]
public void IsBoolean_InvalidBoolRepresentations_ReturnsFalse(object candidate)
{
Assert.That(BooleanService.IsBoolean(candidate), Is.False);
}
EDIT: wrote the tests in a slightly different way, that I think communicates intent a little better.
Although I agree it's best practice to separate the values in order to more easily identify the error. I think one still has to use their own common sense and follow such rules as guidelines and not as an absolute. You want to minimize assertion counts in a unit test, but what's generally most important is to insure a single concept per test.
In your specific case, given the simplicity of the function, I think that the one unit test you provided is fine. It's easy to read, simple, and clear. It also tests the function thoroughly and if ever it were to break somewhere down the line, you would be able to quickly identify the source and debug it.
As an extra note, in order to maintain good unit tests, you'll want to always keep them up to date and treat them with the same care as you do the actual production code. That's in many ways the greatest challenge. Probably the best reason to do Test Driven Development is how it actually allows you to program faster in the long run because you stop worrying about breaking the code that exists.
It's best practice to split each of the values you want to test into separate unit tests. Each unit test should be named specifically to the value you're passing and the expected result. If you were changing code and broke just one of your tests, then that test alone would fail and the other 15 would pass. This buys you the ability to instantly know what you broke without then having to debug the one unit test and find out which of the Asserts failed.
Hope this helps.
I can't comment on "Best Practice" because there is no such thing.
I agree with what Ayende Rahien says in his blog:
At the end, it boils down to the fact that I don’t consider tests to
be, by themselves, a value to the product. Their only value is their
binary ability to tell me whatever the product is okay or not.
Spending a lot of extra time on the tests distract from creating real
value, shippable software.
If you put them all in one test and this test fails "somewhere", then what do you do? Either your test framework will tell you exactly which line it failed on, or, failing that, you step through it with a debugger. The extra effort required because it's all in one function is negligible.
The extra value of knowing exactly which subset of tests failed in this particular instance is small, and overshadowed by the ponderous amount of code you had to write and maintain.
Think for a minute the reasons for breaking them up into individual tests. It's to isolate different functionality and to accurately identify all the things that went wrong when a test breaks. It looks like you might be testing two things: Boolean and Not Boolean, so consider two tests if your code follows two different paths. The bigger point, though, is that if none of the tests break, there are no errors to pinpoint.
If you keep running them, and later have one of these tests fail, that would be the time to refactor them into individual tests, and leave them that way.
I am working on some unittest projects in VS 2008 in C#, i created one simple small method for unit test?
public int addNumber(int a, int b)
{
return a + b;
}
well i created a unit test method as below,
[TestMethod()]
public void addNumberTest()
{
Mathematical target = new Mathematical(); // TODO: Initialize to an appropriate value
int a = 4; // TODO: Initialize to an appropriate value
int b = 2; // TODO: Initialize to an appropriate value
int expected = 0; // TODO: Initialize to an appropriate value
int actual;
actual = target.addNumber(a, b);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
}
But when i try to run the unittest project ,
I am receiving an Inconclusive message. My question is
what exactly the Inconclusive is and when it comes into the picture?
what are the necessary things, i need to do to make my unit test passed?
You need to decide what the criteria is for a unit test to be considered passed. There isn't a blanket answer to what makes a unit test pass. The specifications ultimately dictate what constitutes a passing unit test.
If the method you are testing is indeed just adding two numbers, than the Assert.AreEqual(expected,actual) is probably enough for this particular unit test. You may also want to check Assert.IsTrue(expected>0) That may be another assertion you could tack on to this unit test.
You'll want to test it again though with other values like negatives, zeros, and really large numbers.
You won't need the Inconclusive operator for your unit tests of the addNumber method. That assertion would be more useful when dealing with objects and threads possibly. Calling the Inconclusive assertion like you have will always fail and always return the string passed into it.
I have been used to following code pattern while writing my test
public void TestMethod_Condition_Output()
{
//Arrange----------------
Mock<x> temp = new Mock<x>();
temp.setup.......
//Act--------------------
classinstance.TestMethod()
//Assert------------------
temp.VerifyAll();
Assert.AreNotEqual(.....)
}
I have been used to do the VerifyAll() before performing Assertions. But lately on some online examples, I have seen people doing Assertion first and then VerifyAll, if any. I do feel that my way is the correct way unless I am missing something.
Could you please alert me if I am missing anything.
In my opinion, the verify should come after the asserts. I want the asserts close to the invocation of the method under test as they are documenting what the method does. The verifications of the mock invocations are detailing how the class uses it's dependencies. This is less important to tie directly to the method itself.
In a sense the mocking of the dependencies becomes a wrapper around the actual test itself. This makes the test more understandable (to me, anyway, YMMV). My tests then follow this pattern:
Arrange
Mock
Set up expectations for dependencies
Set up expected results
Create class under test
Act
Invoke method under test
Assert
Assert actual results match expected results
Verify that expectations were met
I don't know that I would be pedantic about it, but this is the order that makes the most sense to me.
In a AAA style testing I do not use VerifyAll but rather than verify methods were called explicitly as part of the unit of test. Within the Arrange area I only setup methods that need to return a value.
using Rhino as an example...
//Arrange
mockedInterface.Stub(x => x.SomeMethod1()).Returns(2);
...
//Assert
mockedInterface.AssertWasCalled(x => x.SomeMethod1());
mockedInterface.AssertWasCalled(x => x.SomeMethod2());
Assert.AreEqual(...); // stanmdard NUnit asserttions
I do not need to setup the expected call to SomeMethod2() if it does not return anything.
With Loose mocks there is no real need to call VerifyAll as calls to other methods would not fail the test (unless a return is needed then it is required in the Arrange section).
The amount of assertions should be kept to a minimum (create more tests if it gets too large) and the order of them should not really matter either.