Is there any point in Unit-Testing a method that the only thing it does is delegate work on another object? Example:
class abc {
...
public void MoveLeft()
{
fallingPiece.MoveLeft();
}
...
}
I am doing Unit-Tests for some existing classes I have, for learning purposes. It seems kinda odd to do a Unit-Test for this MoveLeft() method, for example. But I am unsure how would it have been had I done Test-First.
Thanks
Will your code break if I do this ? If it would, then you need a test to catch it.
class abc {
...
public void MoveLeft()
{
// fallingPiece.MoveLeft();
}
...
}
Assumptions: abc is a public / exposed type and fallingPiece is a dependency. If this holds, then you need a test to test the MoveLeft behavior. If it isn't a public type, then you need a test for the public type XYZ that uses abc as a colloborator/dependency. You don't directly test it but it still needs to be tested.
My understanding of unit tests is that they are there to ensure that the logic inside a method stays the same when you didn't intend for it to change, and this method has no logic in it. We have a lot of pass-through methods like that in the code base where I work. Ostensibly, they're "Controller" classes, but in most cases all they do is pass through to the data layer.
Yes, you can unit test them, assuming you have a way to mock fallingPiece. If you actually plan on expanding the MoveLeft method to include logic, it's probably a good idea.
However, to my comment above, it's probably a better move to just inline the method until you actually need to introduce logic around moving left.
One case that this method can fail is when fallingPiece is null when Abc.MoveLeft gets called. Having a test case that builds a legitimate abc and calls abc.MoveLeft might be good idea.
something like
CanMoveLeft()
{
Abc abc =new Abc();
abc.MoveLeft();
Assert.That( abc.fallingPice has moved to left)
}
Related
In brief: What is the pattern called in the following code, and how should it be tested?
The purpose of the code is to encapsulates a number of actions on a zip file (written in C#, although the pattern is language independent):
public class ZipProcessor
{
public ZipProcessor(string zipFilePath) { ... }
public void Process()
{
this.ExtractZip();
this.StepOne();
this.StepTwo();
this.StepThree();
this.CompressZip();
}
private void ExtractZip() { ... }
private void CompressZip() { ... }
private void StepOne() { ... }
private void StepTwo() { ... }
private void StepThree() { ... }
}
The actual class has around 6 steps, and each step is a short method, 5-15 lines long. The order of the steps is not important, but Extract and Compress must always come first and last respectively. Also, StepTwo takes much longer to run than the rest of the steps.
The following are options I can think of for testing the class:
Only call the public Process method, and only check the result of one step in each test method (pro: clean, con: slow, because each test method calls StepTwo, which is slow, even though it doesn't care about the result of StepTwo)
Test the private steps directly using an accessor or wrapper (pro: simple, clear relation to what is run during a test and what is actually tested, con: still slow: extracts and compresses multiple times, hacky: need to use a private accessor or dynamic wrapper, or make the steps internal in order to access them)
Have only one test method that calls a bunch of smaller helper test methods (pro: fast, models the class more closely, con: violates "one assert per test method", would still need to run multiple times for different scenarios, ex. StepOne has different behavior based on input)
I'm a bit late to the discussion, but this is a Sergeant Method.
A quick google returns "We call the bigger method here as 'sergeant' method, which basically calls other private methods and marshaling them. It may have bits and pieces of code here and there. Each of these private methods is about one particular thing. This promotes cohesion and makes sergeant method read like comments".
As for how you can test it - your example presumably violates SRP because you have a zip compressor/decompressor (one thing) and then step1/2/3. You could extract the private method invocations into other classes and mock those for your test.
I disagree that Chain-of-Responsibility makes much sense here - the compressor shouldn't need to know about the decompressor (unless they're the same class) or the reason why it's doing the decompression. The processing classes (Step1/2/3) shouldn't care that the data they're working with was compressed before, etc.
The strategy pattern doesn't really make sense either - just because you can swap the implementation of extractZip or compressZip doesn't mean you have a strategy pattern.
There's not really a pattern reflected here, but you could rewrite your code to use the Strategy or Chain of Responsibility patterns, as pointed out Paul Michalik. As is, you basically just have a custom workflow defined for your application's needs. Using the Chain of Responsibility pattern, each step would be its own class which you could test independently. You may want to then write an integration test which ensures the whole process works end-to-end (component or acceptance level test).
Consider to split it into 2+ classes - ExtractZip/Compress and process or 1 class ExtractZip/Compress with delegate in the middle.
It's a Strategy. Depending on your testing scenario you can derive from ProcessorMock (or implement it if its an interface) and override the methods not relevant to test by proper stubs. However, usually, the more flexible pattern for such cases is Chain of Responsibility...
I follow the naming convention of
MethodName_Condition_ExpectedBehaviour
when it comes to naming my unit-tests that test specific methods.
for example:
[TestMethod]
public void GetCity_TakesParidId_ReturnsParis(){...}
But when I need to rename the method under test, tools like ReSharper does not offer me to rename those tests.
Is there a way to prevent such cases to appear after renaming? Like changing ReSharper settings or following a better unit-test naming convention etc. ?
A recent pattern is to groups tests into inner classes by the method they test.
For example (omitting test attributes):
public CityGetterTests
{
public class GetCity
{
public void TakesParidId_ReturnsParis()
{
//...
}
// More GetCity tests
}
}
See Structuring Unit Tests from Phil Haack's blog for details.
The neat thing about this layout is that, when the method name changes,
you'll only have to change the name of the inner class instead of all
the individual tests.
I also started with this convertion, however ended up with feeling that is not very good. Now I use BDD styled names like should_return_Paris_for_ParisID.
That makes my tests more readable and alsow allows me to refactor method names without worrying about my tests :)
I think the key here is what you should be testing.
You've mentioned TDD in the tags, so I hope that we're trying to adhere to that here. By that paradigm, the tests you're writing have two purposes:
To support your code once it is written, so you can refactor without fearing that you've broken something
To guide us to a better way of designing components - writing the test first really forces you to think about what is necessary for solving the problem at hand.
I know at first it looks like this question is about the first point, but really I think it's about the second. The problem you're having is that you've got concrete components you're testing instead of a contract.
In code terms, that means that I think we should be testing interfaces instead of class methods, because otherwise we expose our test to a variety of problems associated with testing components instead of contracts - inheritance strategies, object construction, and here, renaming.
It's true that interfaces names will change as well, but they'll be a lot more rigid than method names. What TDD gives us here isn't just a way to support change through a test harness - it provides the insight to realise we might be going about it the wrong way!
Take for example the code block you gave:
[TestMethod]
public void GetCity_TakesParidId_ReturnsParis(){...}
{
// some test logic here
}
And let's say we're testing the method GetCity() on our object, CityObtainer - when did I set this object up? Why have I done so? If I realise GetMatchingCity() is a better name, then you have the problem outlined above!
The solution I'm proposing is that we think about what this method really means earlier in the process, by use of interfaces:
public interface ICityObtainer
{
public City GetMatchingCity();
}
By writing in this "outside-in" style way, we're forced to think about what we want from the object a lot earlier in the process, and it becoming the focus should reduce its volatility. This doesn't eliminate your problem, but it may mitigate it somewhat (and, I think, it's a better approach anyway).
Ideally, we go a step further, and we don't even write any code before starting the test:
[TestMethod]
public void GetCity_TakesParId_ReturnsParis
{
ICityObtainer cityObtainer = new CityObtainer();
var result = cityObtainer.GetCity("paris");
Assert.That(result.Name, Is.EqualTo("paris");
}
This way, I can see what I really want from the component before I even start writing it - if GetCity() isn't really what I want, but rather GetCityByID(), it would become apparent a lot earlier in the process. As I said above, it isn't foolproof, but it might reduce the pain for this particular case a bit.
Once you've gone through that, I feel that if you're changing the name of the method, it's because you're changing the terms of the contract, and that means you should have to go back and reconsider the test (since it's possible you didn't want to change it).
(As a quick addendum, if we're writing a test with TDD in mind, then something is happening inside GetCity() that has a significant amount of logic going on. Thinking about the test as being to a contract helps us to separate the intention from the implementation - the test will stay valid no matter what we change behind the interface!)
I'm late, but maybe that Can be still useful. That's my solution (Assuming you are using XUnit at least).
First create an attribute FactFor that extends the XUnit Fact.
public class FactForAttribute : FactAttribute
{
public FactForAttribute(string methodName = "Constructor", [CallerMemberName] string testMethodName = "")
=> DisplayName = $"{methodName}_{testMethodName}";
}
The trick now is to use the nameof operator to make refactoring possible. For example:
public class A
{
public int Just2() => 2;
}
public class ATests
{
[FactFor(nameof(A.Just2))]
public void Should_Return2()
{
var a = new A();
a.Just2().Should().Be(2);
}
}
That's the result:
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 have a method in a class for which they are a few different outcomes (based upon event responses etc). But this is a single atomic function which is to used by other applications.
I have broken down the main blocks of the functionality that comprise this function into different functions and successfully taken a Test Driven Development approach to the functionality of each of these elements. These elements however aren't exposed for other applications would use.
And so my question is how can/should i easily approach a TDD style solution to verifying that the single method that should be called does function correctly without a lot of duplication in testing or lots of setup required for each test?
I have considered / looked at moving the blocks of functionality into a different class and use Mocking to simulate the responses of the functions used but it doesn't feel right and the individual methods need to write to variables within the main class (it felt really heath robinson).
The code roughly looks like this (i have removed a lot of parameters to make things clearer along with a fair bit of irrelevant code).
public void MethodToTest(string parameter)
{
IResponse x = null;
if (function1(parameter))
{
if (!function2(parameter,out x))
{
function3(parameter, out x);
}
}
// ...
// more bits of code here
// ...
if (x != null)
{
x.Success();
}
}
I think you would make your life easier by avoiding the out keyword, and re-writing the code so that the functions either check some condition on the response, OR modify the response, but not both. Something like:
public void MethodToTest(string parameter)
{
IResponse x = null;
if (function1(parameter))
{
if (!function2Check(parameter, x))
{
x = function2Transform(parameter, x);
x = function3(parameter, x);
}
}
// ...
// more bits of code here
// ...
if (x != null)
{
x.Success();
}
}
That way you can start pulling apart and recombining the pieces of your large method more easily, and in the end you should have something like:
public void MethodToTest(string parameter)
{
IResponse x = ResponseBuilder.BuildResponse(parameter);
if (x != null)
{
x.Success();
}
}
... where BuildResponse is where all your current tests will be, and the test for MethodToTest should now be fairly easy to mock the ResponseBuilder.
Your best option would indeed be mocking function1,2,3 etc. If you cannot move your functions to a separate class you could look into using nested classes to move the functions to, they are able to access the data in the outer class. After that you should be able to use mocks instead of the nested classes for testing purposes.
Update: From looking at your example code I think you could get some inspiration by looking into the visitor pattern and ways of testing that, it might be appropriate.
In this case I think you would just mock the method calls as you mentioned.
Typically you would write your test first, and then write the method in a way so that all of the tests pass. I've noticed that when you do it this way, the code that's written is very clean and to the point. Also, each class is very good about only having a single responsibility that can easily be tested.
I don't know what's wrong, but something doesn't smell right, and I think there maybe a more elegant way to do what you're doing.
IMHO, you have a couple options here:
Break the inner functions out into a different class so you can mock them and verify that they are called. (which you already mentioned)
It sounds like the other methods you created are private methods, and that this is the only public interface into those methods. If so, you should be running those test cases through this function, and verifying the results (you said that those private methods modify variables of the class) instead of testing private methods. If that is too painful, then I would consider reworking your design.
It looks to me like this class is trying to do more than one thing. For example, the first function doesn't return a response but the other two do. In your description you said the function is complex and takes a lot of parameters. Those are both signs that you need to refactor your design.
Is there a way to know when code is being called from running a test method?
bool MyMethod()
{
if ( /* are we running a test? */ )
{
return true; // otherwise this will fail from the automated build script
}
else
{
// run the proper code
}
}
and please spare me the "this is a really bad idea" comments :)
You recognize this may be a bad idea, but you may not be aware of the alternatives. You should look into mocking frameworks - they can provide a way to inject alternative implementations into your code at runtime in your unit tests. This is an established practice to allow code to behave differently in test and production.
On to the main question.
This depends on the unit test framework you are using. I'm not aware of a specific feature in NUnit (for example) that reports you are in a test. Other frameworks (like MS Test) may very well provide this. However, it's easy to do yourself.
If you're binding to source code, just use a #define directive to conditionally define some variable you can branch on.
If you're binding to a library, I would recommend creating your own class that you use to track whether you are in a unit test or real code, and set that class up in the TestFixture setup method to indicate you are running a test. You could also use the Environment.SetEnvironmentVariable as a way of avoiding writing a special class.
Ok, I'll spare you my "this is a really bad idea" comment.
You can just give the method a parameter bool isTestMode.
The approach outlined in your question is a really bad idea.
A cleaner approach if you want a method to behave differently under test than otherwise, is to refactor out an interface with the method, and inject a different implementation at test time.
E.g.:
// Interface whose implementation changes under testing
public interface IChangesUnderTest
{
void DoesSomething();
}
// Inject this in production
public class ProductionCode : IChangesUnderTest
{
void DoesSomething() { /* Does stuff */ }
}
// Inject this under test
public class TestCode : IChangesUnderTest
{
void DoesSomething() { /* Does something else */ }
}
You should check the attribute of calling methods by reflection! I will not mention that this is a bed idea, because you know it as I see ;)
Here's my suggestion.
Instead of checking the context, just add in some conditional bug code:
#if DEBUG
/* assume you are running in a test environment here */
#endif
This is almost not bad. And if it isn't exactly what you need, you can look into #define-ing "TEST" for when you might want your test code to not execute during regular debugging.
If you use a test framework, and know the testAssemblyName, you can do as follows:
bool IsInUnitTest = AppDomain.CurrentDomain.GetAssemblies()
.Any(a => a.FullName.StartsWith(testAssemblyName));
To be more specificly, if you use NUnit,
bool IsRunningFromNUnit =
AppDomain.CurrentDomain.GetAssemblies().Any(
a=> a.FullName.ToLowerInvariant().StartsWith("nunit.framework"));
if you use MSTest, then replace testAssemblyName as corresponding AssemblyName, maybe is Microsoft.VisualStudio.QualityTools.UnitTestFramework.