I'm trying to implement the strategy pattern using TDD. Each strategy item implements an interface. What's the best way to do this with TDD?
Do you have to create a test fixture for each implementation of the interface testing the same methods but on each implementation?
Any articles detailing the approach to take would be gratefully welcomed :)
I think I would write a separate test class for each implementation of the strategy.
You could make an abstract class for all of these to inherit from. This would help you make sure you implement all the tests for every strategy, but has the slight disadvantage that you'd have to implement stub methods at least before each test class would even compile.
Write a test that is failing
Write ugly code to make that test pass
Refactor to make the code better
In step 2, write code that isn't implementing the Strategy Pattern (simplest thing that works, even if duplicated code is present).
Then in step 3 you refactor each class, one at a time, towards the Strategy pattern if it still makes sense to do so.
If you're truly doing TDD then you don't start out with a pattern -- you refactor to it.
Related
Can we write generic test cases in BDD?
I mean that we have a generic test class, and we could have an instantiator to instantiate the value that we want and then execute the test?
BDD has a strong focus on customer communication, so I would recommend not to write generic test cases, as it will likely be harder for a customer to understand. For example, I would prefer:
authenticates_user_with_4_digit_password
authenticates_user_with_8_digit_password
However, you should do what works best for your situation and if your customer understands a generic test case, then you should use it.
In TDD how should you continue when you know what your final outcome should be, but not the processing steps you need to get there?
For example your class is being passed an object whose API is completely new to you, You know the class has the information you need but you don't know how to retrieve it yet: How would you go about testing this?
Do you just focus on the desired result ignoring the steps?
Edit 1
package com.wesley_acheson.codeReview.annotations;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
public class AnnotationPresenceWarner implements AnnotationProcessor {
private final AnnotationProcessorEnvironment environment;
public AnnotationPresenceWarner(AnnotationProcessorEnvironment env) {
environment = env;
}
public void process() {
//This is what I'm testing
}
}
I'm trying to test this incomplete class. I want to test I have the right interactions with AnnotationProcessorEnvironment within the process method. However I'm unsure from the API docs what the right interaction is.
This will produce a file that contains details on the occurrence of each annotation within a source tree.
The actual file writing will probably be delegated to another class however. So this class' responsiblity is to create a representation of the annotation occurrences and pass that to whatever classes need to move it.
In non TDD I'd probably invoke a few methods set a breakpoint and see what they return.
Anyway I'm not looking for a solution to this specific example more sometimes you don't know how to get from A to B and you'd like your code to be test driven.
I'm basing my answer on this video:
http://misko.hevery.com/2008/11/11/clean-code-talks-dependency-injection/
If you have a model/business logic class that's supposed to get some data from a service then I'd go about this way:
Have your model class take the data that it needs in the constructor, rather than the service itself. You could then mock the data and unit test your class.
Create a wrapper for the service, you can then unit test then wrapper.
Perform a fuller test where you actually pass the data from the wrapper to the model class.
General Answer
TDD can be used to solve a number of issues, the first and foremost is to ensure that code changes do not break existing code in regards to their expected behavior. Thus, if you've written a class with TDD, you write some code first, see that it fails, then write the behavior to make it green without causing other tests to become red.
The side-effect of writing the test cases is that now you have Documentation. This means that TDD actually provides answers to two distinct problems with code. When learning a new API, regardless of what it is, you can use TDD to explore it's behavior (granted, in some frameworks this can be very difficult). So, when you are exploring an API, it's ok to write some tests to provide documentation to it's use. You can consider this a prototyping step as well, just that prototyping assumes you throw it away when complete. With the TDD approach, you keep it, so you can always return back to it long after you've learned the API.
Specific Answer to the Example Given
There are a number of approaches which attempt to solve the problem with the AnnotationProcessor. There is an Assertion framework which addresses the issue by loading the java code during the test and asserting the line which the error/warning occurs. And here on Stack overflow
I would create a prototype without the testing to get knowledge of how the api is working. When I got that understanding, I would continue on the TDD cycle on my project
I agree with Bassetassen. First do a spike to understand what is this external API call does and what you need for your method. Once you are comfortable with the API you know how to proceed with TDD.
Never ever Unit Test against an unknown API. Follow the same principle is if you didn't own the code. Isolate all the code you are writing from the unknown or unowned.
Write your unit tests as if the environmental processor was going to be code that you were going to TDD later.
Now you can follow #Tom's advice, except drop step 1. Step 2's unit tests now are just a matter of mapping the outputs of the wrapper class to calls on the API of the unknown. Step two is more along the lines of an integration test.
I firmly believe changing your flow from TDD to Prototyping to TDD is a loss in velocity. Stay with the TDD until you are done, then prototype.
I'm reading through the (still beta) rspec book by the prag progs as I'm interested in behavioral testing on objects. From what I've gleaned so far (caveat: after only reading for 30 min), the basic idea is that I want ensure my object behaves as expected 'externally' i.e. in its output and in relation to other objects.
Is it true then that I should just be black box testing my object to ensure the proper output/interaction with other objects?
This may be completely wrong, but given all of the focus on how my object behaves in the system, it seems this is ideology one would take. If that's so, how do we focus on the implementation of an object? How do I test that my private method is doing what I want it to do for all different types of input?
I suppose this question is maybe valid for all types of testing?? I'm still fairly new to TDD and BDD.
If you want to understand BDD better, try thinking about it without using the word "test".
Instead of writing a test, you're going to write an example of how you can use your class (and you can't use it except through public methods). You're going to show why your class is valuable to other classes. You're defining the scope of your class's responsibilities, while showing (through mocks) what responsibilities are delegated elsewhere.
At the same time, you can question whether the responsibilities are appropriate, and tune the methods on your class to be as intuitively usable as possible. You're looking for code which is easy to understand and use, rather than code which is easy to write.
If you can think in terms of examples and providing value through behaviour, you'll create code that's easy to use, with examples and descriptions that other people can follow. You'll make your code safe and easy to change. If you think about testing, you'll pin it down so that nobody can break it. You'll make it hard to change.
If it's complex enough that there are internal methods you really want to test separately, break them out into another class then show why that class is valuable and what it does for the class that uses it.
Hope this helps!
I think there are two issues here.
One is that from the BDD perspective, you are typically testing at a higher level than from the TDD perspective. So your BDD tests will assert a bigger piece of functionality than your TDD tests and should always be "black box" tests.
The second is that if you feel the need to test private methods, even at the unit test level, that could be a code smell that your code is violating the Single Responsibilty Principle
and should be refactored so that the methods you care about can be tested as public methods of a different class. Michael Feathers gave an interesting talk about this recently called "The Deep Synergy Between Testability and Good Design."
Yes, focus on the exposed functionality of the class. Private methods are just part of a public function you will test. This point is a bit controversial, but in my opinion it should be enough to test the public functionality of a class (everything else also violates the OOP principle).
A very specific question from a novice to TDD:
I separate my tests and my application into different packages. Thus, most of my application methods have to be public for tests to access them. As I progress, it becomes obvious that some methods could become private, but if I make that change, the tests that access them won't work. Am I missing a step, or doing something wrong, or is this just one downfall of TDD?
This is not a downfall of TDD, but rather an approach to testing that believes you need to test every property and every method. In fact you should not care about private methods when testing because they should only exist to facilitate some public portion of the API.
Never change something from private to public for testing purposes!
You should be trying to verify only publicly visible behavior. The rest are implementation details and you specifically want to avoid testing those. TDD is meant to give you a set of tests that will allow you to easily change the implementation details without breaking the tests (changing behavior).
Let’s say I have a type: MyClass and I want to test the DoStuff method. All I care about is that the DoStuff method does something meaningful and returns the expected results. It may call a hundred private methods to get to that point, but I don't care as the consumer of that method.
You don't specify what language you are using, but certainly in most of them you can put the tests in a way that have more privileged access to the class. In Java, for example, the test can be in the same package, with the actual class file being in a different directory so it is separate from production code.
However, when you are doing real TDD, the tests are driving the class design, so if you have a method that exists just to test some subset of functionality, you are probably (not always) doing something wrong, and you should look at techniques like dependency injection and mocking to better guide your design.
This is where the old saying, "TDD is about design," frequently comes up. A class with too many public methods probably has too many responsibilities - and the fact that you are test-driving it only exposes that; it doesn't cause the problem.
When you find yourself in this situation, the best solution is frequently to find some subset of the public methods that can be extracted into a new class ("sprout class"), then give your original class an instance variable of the sprouted class. The public methods deserve to be public in the new class, but they are now - with respect to the API of the original class - private. And you now have better adherence to SRP, looser coupling, and higher cohesion - better design.
All because TDD exposed features of your class that would otherwise have slid in under the radar. TDD is about design.
At least in Java, it's good practice to have two source trees, one for the code and one for the tests. So you can put your code and your tests in the same package, while they're still in different directories:
src/org/my/xy/X.java
test/org/my/xy/TestX.java
Then you can make your methods package private.
I have a class called FooJob() which runs on a WCF windows service. This class has only 2 public methods, the constructor, and a Run() method.
When clients call my service, a Dim a new instance of the Job class, pass in some parameters to the ctor, then call Run()...
Run() will take the parameters, do some logic, send a (real time) request to an outside data vendor, take the response, do some business logic, then put it in the database...
Is it wise to only write a single unit test then (if even possible) on the Run() function? Or will I wind up killing myself here? In this case then should I drill into the private functions and unit test those of the FooJob() class? But then won't this 'break' the 'only test behavior' / public interface paradigm that some argue for in TDD?
I realize this might be a vague question, but any advice / guidance or points in the right direction would be much appreciated.
Drew
do some logic, send a (real time) request to an outside data vendor, take the response, do some business logic, then put it in the database
The problem here is that you've listed your class as having multiple responsibilities... to be truly unit testable you need to follow the single responsibility principle. You need to pull those responsibilities out into separate interfaces. Then, you can test your implementations of these interfaces individually (as units). If you find that you can't easily test something your class is doing, another class should probably be doing that.
It seems like you'd need at least the following:
An interface for your business logic.
An interface defining the request to the outside vendor.
An interface for your data repository.
Then you can test that business logic, the process of communicating with the outside vendor, and the process of saving to your database separately. You can then mock out those interfaces for testing your Run() method, simply ensuring that the methods are called as you expect.
To do this properly, the class's dependencies (the interfaces defined above) should ideally be passed in to its constructor (i.e. dependency injection), but that's another story.
My advice would be to let your tests help with the design of your code. If you are struggling to execute statements or functions then your class is doing too much. Follow the single-responsibility-priciple, add some interfaces (allowing you to mock out the complicated stuff), maybe even read Fowler's 'Refactoring' or Feather's 'Working With Legacy Code', these taught me more about TDD than any other book to date.
It sounds like your run method is trying to do too much I would separate it up but if you're overall design won't allow it.
I would consider making the internal members protected then inheriting from the class in your test class to test them. Be careful though I have run into gotchas doing this because it doesn't reset the classes state so Setup and TearDown methods are essential.
Simple answer is - it depends. I've written a lot of unit tests that test the behaviour of private methods; I've done this so that I can be happy that I've covered various inputs and scenarios against the methods.
Now, many people think that testing private methods is a bad idea, since it's the public methods that matter. I get this idea, but in my case the public method for these private calls was also just a simple Run() method. The logic of the private methods included reading from config files and performing tasks on the file system, all "behind the scenes".
Had I just created a unit test that called Run() then I would have felt that my tests were incomplete. I used MSTest to create accessors for my class, so that I could call the private methods and create various scenarios (such as what happens when I run out of disk space, etc).
I guess it's each to their own with this private method testing do/or don't do argument. My advice is that, if you feel that your tests are incomplete, in other words, require more coverage, then I'd recommend testing the private methods.
Thanks everyone for the comments. I believe you are right - I need to seperate out into more seperate classes. This is one of the first projects im doing using true TDD, in that I did no class design at all and am just writing stub code... I gotta admit, I love writing code like this and the fact I can justify it to my mangagment with years of backed up successful results is purely friggin awesome =).
The only thing I'm iffy about is over-engineering and suffering from class-bloat, when I could have just written unit tests against my private methods... I guess common sense and programmers gut have to be used here... ?