So, i'm new to unit testing, and even more so to test first development. Is it valid for me to have just a single assert.isTrue statement in my unit test where I pass in my method and a valid parameter, and compare it to the known good answer?
Method
public static string RemoveDash(string myNumber)
{
string cleanNumber = myNumber.Replace("-","");
return cleanNumber;
}
Test
[TestMethod()]
public void TestRemoveDash()
{
Assert.IsTrue(RemoveDash("50-00-0")=="50000");
}
That's pretty valid if it tests the functionality of your method, which it very much seems to be doing.
Might consider using Equals here instead, but it doesn't really matter. Also, I know this is a test example, but always make sure to test cases where the input is not what is expected as well as whatever other valid forms it can come in (this can be in the same test method or a different one depending on your preference)
Testers sometimes read our tests so I attempt to make them as readble as possible. I would prefer to use the following, rather than the single Assert:
[TestMethod()]
public void TestRemoveDash()
{
string expected = "50000";
string actual = RemoveDash("50-00-0");
Assert.AreEqual(expected,actual);
}
The only comment is to use Assert.AreEqual instead of Assert.IsTrue:
Assert.IsAreEqual("50000", RemoveDash("50-00-0"));
The reason for that is that if the test fail the error message you get is more descriptive of what was meant to happen and what actually did happen. A message that says "Expected value <50000> but was actually <50-00-0>" is a lot better than "Expected value to be true, but was false."
As a rule of thumb, whenever you find yourself wanting to use Assert.IsTrue, go through Assert methods and see if there is a better method to test your expectation (e.g. Assert.IsInstanceOfType, Assert.IsNotNull, etc).
This seems perfectly valid - however, why not include a few other tests in that method, along the same lines but testing that e.g. RemoveDash("-") == "" and RemoveDash("-5") == "5" etc?
Related
If a public method only calls external methods and contains no special logic within, should I add unit test on it?
The method below only calls external methods and use return values to construct a student object.
public student GetStudent(int ID){
var n = GetName(ID);
var a = GetAddress(ID);
return new student{
name = n;
address = a;
}
}
If I have a separate set of unit tests on GetName() and GetAddress() method already, do I still need to have unit tests on GetStudent() method?
Since tests already ensure GetName() and GetAddress() will return valid result(e.g. not null), GetStudent() should be fine accordingly.
I find it is rather difficult to decide whether I should do test on a method or not. May you also recommend some external resources (e.g. website, book, blog) on this regards?
Thank you.
you need to specify GetStudent behavior in test. for example what should happen in case of unreal id? exeption/null this should be described in test. you need to check final objct: can/cant name be null, can/cant address be null. it will be good documentation for GetStudent function
The answer is "primarily opinion-based" but in common, you can test this method and check:
Method does not return null
All fields of student class are set
You should mock GetName and GetAddress method and check that both of them are called with correct argument
So, this example is very simple, yes. But, maybe in future, you'll have some logic in this method and you need to ensure that everything is OK.
It's my philosophy that I always unit test methods that are exposed, no matter how trivial they are. Reason is if someone else is going to be working on this code, and they decide they want to change things, there is no Quality Assurance that their new code will break the system, unless you have Unit Tests. Unit Tests are there to make to make sure the code is of good quality and to make sure that other developers don't inherently break the system.
What is the best way to unit test a method that doesn't return anything? Specifically in c#.
What I am really trying to test is a method that takes a log file and parses it for specific strings. The strings are then inserted into a database. Nothing that hasn't been done before but being VERY new to TDD I am wondering if it is possible to test this or is it something that doesn't really get tested.
If a method doesn't return anything, it's either one of the following
imperative - You're either asking the object to do something to itself.. e.g change state (without expecting any confirmation.. its assumed that it will be done)
informational - just notifying someone that something happened (without expecting action or response) respectively.
Imperative methods - you can verify if the task was actually performed. Verify if state change actually took place. e.g.
void DeductFromBalance( dAmount )
can be tested by verifying if the balance post this message is indeed less than the initial value by dAmount
Informational methods - are rare as a member of the public interface of the object... hence not normally unit-tested. However if you must, You can verify if the handling to be done on a notification takes place. e.g.
void OnAccountDebit( dAmount ) // emails account holder with info
can be tested by verifying if the email is being sent
Post more details about your actual method and people will be able to answer better.
Update: Your method is doing 2 things. I'd actually split it into two methods that can now be independently tested.
string[] ExamineLogFileForX( string sFileName );
void InsertStringsIntoDatabase( string[] );
String[] can be easily verified by providing the first method with a dummy file and expected strings. The second one is slightly tricky.. you can either use a Mock (google or search stackoverflow on mocking frameworks) to mimic the DB or hit the actual DB and verify if the strings were inserted in the right location. Check this thread for some good books... I'd recomment Pragmatic Unit Testing if you're in a crunch.
In the code it would be used like
InsertStringsIntoDatabase( ExamineLogFileForX( "c:\OMG.log" ) );
Test its side-effects. This includes:
Does it throw any exceptions? (If it should, check that it does. If it shouldn't, try some corner cases which might if you're not careful - null arguments being the most obvious thing.)
Does it play nicely with its parameters? (If they're mutable, does it mutate them when it shouldn't and vice versa?)
Does it have the right effect on the state of the object/type you're calling it on?
Of course, there's a limit to how much you can test. You generally can't test with every possible input, for example. Test pragmatically - enough to give you confidence that your code is designed appropriately and implemented correctly, and enough to act as supplemental documentation for what a caller might expect.
As always: test what the method is supposed to do!
Should it change global state (uuh, code smell!) somewhere?
Should it call into an interface?
Should it throw an exception when called with the wrong parameters?
Should it throw no exception when called with the right parameters?
Should it ...?
Try this:
[TestMethod]
public void TestSomething()
{
try
{
YourMethodCall();
Assert.IsTrue(true);
}
catch {
Assert.IsTrue(false);
}
}
Void return types / Subroutines are old news. I haven't made a Void return type (Unless I was being extremely lazy) in like 8 years (From the time of this answer, so just a bit before this question was asked).
Instead of a method like:
public void SendEmailToCustomer()
Make a method that follows Microsoft's int.TryParse() paradigm:
public bool TrySendEmailToCustomer()
Maybe there isn't any information your method needs to return for usage in the long-run, but returning the state of the method after it performs its job is a huge use to the caller.
Also, bool isn't the only state type. There are a number of times when a previously-made Subroutine could actually return three or more different states (Good, Normal, Bad, etc). In those cases, you'd just use
public StateEnum TrySendEmailToCustomer()
However, while the Try-Paradigm somewhat answers this question on how to test a void return, there are other considerations too. For example, during/after a "TDD" cycle, you would be "Refactoring" and notice you are doing two things with your method... thus breaking the "Single Responsibility Principle." So that should be taken care of first. Second, you might have idenetified a dependency... you're touching "Persistent" Data.
If you are doing the data access stuff in the method-in-question, you need to refactor into an n-tier'd or n-layer'd architecture. But we can assume that when you say "The strings are then inserted into a database", you actually mean you're calling a business logic layer or something. Ya, we'll assume that.
When your object is instantiated, you now understand that your object has dependencies. This is when you need to decide if you are going to do Dependency Injection on the Object, or on the Method. That means your Constructor or the method-in-question needs a new Parameter:
public <Constructor/MethodName> (IBusinessDataEtc otherLayerOrTierObject, string[] stuffToInsert)
Now that you can accept an interface of your business/data tier object, you can mock it out during Unit Tests and have no dependencies or fear of "Accidental" integration testing.
So in your live code, you pass in a REAL IBusinessDataEtc object. But in your Unit Testing, you pass in a MOCK IBusinessDataEtc object. In that Mock, you can include Non-Interface Properties like int XMethodWasCalledCount or something whose state(s) are updated when the interface methods are called.
So your Unit Test will go through your Method(s)-In-Question, perform whatever logic they have, and call one or two, or a selected set of methods in your IBusinessDataEtc object. When you do your Assertions at the end of your Unit Test you have a couple of things to test now.
The State of the "Subroutine" which is now a Try-Paradigm method.
The State of your Mock IBusinessDataEtc object.
For more information on Dependency Injection ideas on the Construction-level... as they pertain to Unit Testing... look into Builder design patterns. It adds one more interface and class for each current interface/class you have, but they are very tiny and provide HUGE functionality increases for better Unit-Testing.
You can even try it this way:
[TestMethod]
public void ReadFiles()
{
try
{
Read();
return; // indicates success
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
it will have some effect on an object.... query for the result of the effect. If it has no visible effect its not worth unit testing!
Presumably the method does something, and doesn't simply return?
Assuming this is the case, then:
If it modifies the state of it's owner object, then you should test that the state changed correctly.
If it takes in some object as a parameter and modifies that object, then your should test the object is correctly modified.
If it throws exceptions is certain cases, test that those exceptions are correctly thrown.
If its behaviour varies based on the state of its own object, or some other object, preset the state and test the method has the correct Ithrough one of the three test methods above).
If youy let us know what the method does, I could be more specific.
Use Rhino Mocks to set what calls, actions and exceptions might be expected. Assuming you can mock or stub out parts of your method. Hard to know without knowing some specifics here about the method, or even context.
Depends on what it's doing. If it has parameters, pass in mocks that you could ask later on if they have been called with the right set of parameters.
What ever instance you are using to call the void method , You can just use ,Verfiy
For Example:
In My case its _Log is the instance and LogMessage is the method to be tested:
try
{
this._log.Verify(x => x.LogMessage(Logger.WillisLogLevel.Info, Logger.WillisLogger.Usage, "Created the Student with name as"), "Failure");
}
Catch
{
Assert.IsFalse(ex is Moq.MockException);
}
Is the Verify throws an exception due to failure of the method the test would Fail ?
So I have something along the lines of this
private List<ConcurrentQueue<int>> listOfQueues = new List<ConcurrentQueue<int>>()
public void InsertInt(int id, int value)
{
listOfQueues[id].Enqueue(value);
}
Is this something I shouldn't be unit testing?
If it is how do I test the InsertInt method without using any other methods?
is it ok to use the method to retrieve the data from the queue to test if the it was enter correctly?
Is this something I should be using mocks for?
You generally do not want to test private members. The point of unit testing is that from the outside, the class takes the specified inputs and (when requested) will give you the correct outputs. You don't care about the implementation of HOW it gives you those outputs, you just care that it gives you the correct outputs for external usage.
To show this, say you create a unit test verifies that your InsertInt() method inserts the int to listOfQueues. Then your requirements change, and you have to change your implementation strategy, and instead of using a List<ConcurrentQueue<int>> it becomes a Dictionary<string, ConcurrentQueue<int>>. This may not actually require a change to your inputs, and your outputs can still pass any output verification, but your InsertInt() unit test will fail because it's hard coded to the implementation.
The better idea is to do unit tests that makes sure that if you call InsertInt() with the correct input, that your output methods will still return the corrected output, as well as creating unit tests that calling InsertInt() with invalid parameters causes exceptions. You can then change everything about your internal implementation and be confident that your class is still working correctly. Unit testing the implementation adds extra over-head while providing very little benefit in testability.
Note that I am NOT saying that this method should not be unit tested, it's just that the unit tests need to be developed in a way that reflects how outside objects will interact with your class.
Yes, you should unit test it. You can use a private accessor to get the listOfQueues.
You must make sure with a unit test that the method behaves as expected with exceptions and that the item really is inserted.
Check out this article on how to unit test private methods http://msdn.microsoft.com/en-us/library/ms184807(v=vs.80).aspx
You should not be testing the behaviour of the queues - this is an implementation detail that you could change without changing the behaviour of the method. for example, you could replace the ConcurrentQueue with another data structure, perhaps a tree, without needing to update the unit tests.
What you are testing is that this method accepts the inputs and stores the value as you expect. Therefore you will need some way of interrogating the state of the system such as
public int GetInt(int id)
Then you test that the method inserts as you expect by retrieving them using the same id.
You should test that the public method returns the results you expect in every case you can think of, and leave it to the method to store the values as it sees fit. Therefore I would probably test the method like this, with different inputs :
[TestCase(1,2,3)] // whatever test cases make sense for you
[TestCase(4,5,6)]
[TestCase(7,8,9)]
[Test]
public void Test_InsertInt_OK( int testId, int testValue, int expectedValue)
{
InsertInt(testId, testValue);
Assert.AreEqual( GetInt(testId), expectedValue )
}
As this method is a public method, it needs to be unit tested.
A quick look at your method would reveal that passing -1 as the value of id would cause an ArgumentOutOfRangeException. This would have been realized during coding if the unit test case for this method had been designed (assuming that many such methods exist).
To check whether the insertion is successful, you can use the method pointed out by #Oskar Kjellin.
If you want to get dirty, then you can use Reflection, to check whether the value has been inserted or not.
// Sample with Queue instead of ConcurrentQueue
private void TestInsertInt(int id, int value)
{
myInstance.InsertInt(id, value);
FieldInfo field = myInstance.GetType().GetField("listOfQueues", BindingFlags.NonPublic | BindingFlags.Instance);
List<Queue<int>> listOfQueues = field.GetValue(myInstance) as List<Queue<int>>;
int lastInserted = listOfQueues[id].Last();
Assert.AreEqual(lastInserted, value);
}
Is this something I shouldn't be unit
testing?
If you are targeting 100% test coverage then yes
If it is how do I test the InsertInt
method without using any other
methods?
Several options:
Use a different accessor method as
you suggest.
Make the container internal and give the unit test assembly access to internals
Factor the container out into a separate class which you pass as a dependency to this class and then in your unit test pass a mock container instead
Use reflection to access the private members
Another hack is to use the PrivateObject.
Personally, I would either use DI(Dependency Injection) or make the private, internal for the sake of Unit Testing!
I currently have the following method:
public void SetNewRandomValue() {
double newValue = numberGenerator.GenerateDouble(
genesValuesInterval.MinimumValue,
genesValuesInterval.MaximumValue
);
this.value = newValue;
}
What should be the guidelines for deciding how many tests (and which tests) to make to this method? I currently have done the following one (only after implementing the method -- that is, not test-first):
var interval = new Interval(-10, 10);
var numberGeneratorMock = new Mock<INumberGenerator>(MockBehavior.Strict);
var numberGenerator = numberGeneratorMock.Object;
double expectedValue = 5.0;
numberGeneratorMock.Setup(ng =>
ng.GenerateDouble(interval.MinimumValue, interval.MaximumValue))
.Returns(expectedValue);
var gene = new Gene(numberGenerator, 0, new Interval(-10, 10));
gene.SetNewRandomValue();
Assert.AreEqual<double>(expectedValue, gene.Value);
that basically just tests one situation. Regression-testingwise I'd say that I can't think of a way of messing up the code, turning it into mal functioning code and still have the test pass, that is, I think the method looks decently covered.
What are your opinions on this? How would you handle this little method?
Thanks
I would examine the code coverage with whatever testing tool you use, if a code coverage is available for your testing framework.
I personally like to work with either Microsoft Testing Tool or NUnit Testing Framework. I can then right-click my tests project and Test with NCover (while using NUnit), which will run the tests and tell me the percentage of code covered for each of my objects and tests.
I say that when you'll be done checking the code coverage which would result of at least a 98% code coverage, your code is likely to be well tested.
I'd recommend taking a look at Pex - it can really help generate the kind of unit tests you're looking for (i.e. figure out the different potential paths and results given a method and return value).
That test looks fine. The only thing you can actually assert about SetNewRandomValue is that the Value member is assigned afterward. You've mocked out the call to GenerateDouble and verified that Value contains the expected number, so you should be good.
You could also write a test to document (and verify) the expected behavior of Gene.SetNewRandomValue when NumberGenerator.GenerateDouble returns a value outside the specified interval.
You could definitely make a case for not unit testing this. IMHO, code inspection is a perfectly valid test methodology. You generally don't test things like property setters/getters, I think this method is simple enough to avoid unit testing for the same reason.
That said, if you really do want to test it, here's what I'd do: I'd test it with a couple values, not just once with 5. (SetNewRandomValue could be implemented as this.value = 5;, which should not pass.) I'd test it with a non-integer number, to confirm there's not a oddball cast to integer in there.
You could test that it's calling GenerateDouble with the proper parameters, though that's really testing an implementation detail. (SetNewRandomValue could be implemented as numberGenerator.GenerateDouble(0, interval.max - interval.min) + interval.min;, and that shouldn't fail the test.) You could use a real random number generator, and do SetNewRandomValue a few thousand times, and test that the values are evenly distributed in your expected range.
The method is doing three things:
Calling numberGenerator.GenerateDouble with genesValuesInterval.MinimumValue as the first parameter,
and with genesValuesInterval.MaximumValue as the second parameter,
and setting this.value to the result of that call.
Your test tests the third of these things, but not the first two. You could write two more tests that check the mock is called with the correct first and second parameters.
Edit (responding to comments below):
If the intended behaviour of this method is to set this.value to a random double within a previously specified range, then the above three tests are useful (assuming genesValuesInterval min and max are the previously specified range and that you have tests in place to assert that numberGenerator.GenerateDouble(min, max) returns a double within the specified range.
If the intended behaviour of this method is just to set this.value to a random double within (Double.MinValue, Double.MaxValue), then the first two tests are unnecessary as this is just an implementation detail.
If the inted
To answer how to test it, you should be able to describe what is the desired behavior.
Looking at your code, I assume that "Gene.SetNewRandomValue" is supposed to set self.Value to a number which falls within the Interval passed to the constructor.
I'm not super familiar with the Mock class, so I may be off base, but it appears that you are not testing that. What if your implementation had this typo?
double newValue = numberGenerator.GenerateDouble(
genesValuesInterval.MinimumValue,
genesValuesInterval.MinimumValue
);
Wouldn't your test still pass?
I hope this doesn't come across as a stupid question but its something I have been wondering about. I wish to write unit test a method which contains some logic to check that certain values are not null.
public void MyMethod(string value1, string value2)
{
if(value1 != null)
{
//do something (throw exception)
}
if(value2 != null)
{
//do something (throw exception)
}
//rest of method
}
I want to test this by passing null values into the method. My question is should I create a unit test for each argument or can I create one unit test which checks what happens if I set value1 to null and then checks what happens if I set value2 to null.
i.e.
[TestMethod]
public void TestMyMethodShouldThrowExceptionIfValue1IsNull()
{
//test
}
[TestMethod]
public void TestMyMethodShouldThrowExceptionIfValue2IsNull()
{
//test
}
or
[TestMethod]
public void TestMyMethodWithNullValues()
{
//pass null for value1
//check
//pass null for value2
//check
}
Or does it make any difference? I think I read somewhere that you should limit yourself to one assert per unit test. Is this correct?
Thanks in advance
Zaps
You should write a unit test for each test case (assertion) to avoid Assertion Roulette.
The "ideal" unit test test one thing only in order to pinpoint errors exactly.
In practice, this is not nearly as important as most TDD proponents state, because tests don't fail frequently, and finding out which assert failed takes almost no time compared with the rest of the work involved in investigating and fixing the problem.
Doing extra work when writing the tests to save yourself work when it fails (which may never happen) is a form of YAGNI.
If having multiple methods is no extra work beyond typing more method declarations, you should do it, but if it leads to duplicated setup code, I see absolutely nothing wrong with testing several conditions in one test method.
If you are doing two tests in the same test method, your tests are not doing "unit-test".
For instance, what if the test for the first null value fails ?
If both tests are in the same test method, the second test will probably not be executed ; which means the test on the second null value depends on the test on the first null value.
On the other hand, if you have two separate test methods, you can test each case in perfect isolation.
Judging from the code of your MyMethod method, there is no link between the two conditions ; which means there shouldn't probably be any dependancy between the tests for those two conditions.
So : you should use two distinct tests.
To extrapolate to a non-technical thought.
Say you have a car, and you want to test the color.
Tests might be:
Car is red.
Car is blue.
Car is painted.
Now it might make sense to have "Painted" and "blue", but they really are different things. And if you test red and blue, it will always fail - or the failure would not make sense from an isolation standpoint.
Always test ONE thing at a time as you suggest, and many things comprise the test suite.