8

I have been designing and developing code with TDD style for a long time. What disturbs me about TDD is writing tests for code that does not contain any business logic or interesting behaviour. I know TDD is a design activity more than testing but sometimes I feel it's useless to write tests in these scenarios.

For example I have a simple scenario like "When user clicks check button, it should check file's validity". For this scenario I usually start writing tests for presenter/controller class like the one below.

@Test
public void when_user_clicks_check_it_should_check_selected_file_validity(){
    MediaService service =mock(MediaService);
    View view =mock(View);

    when(view.getSelectedFile).thenReturns("c:\\Dir\\file.avi");

    MediaController controller =new MediaController(service,view);
    controller.check();

    verify(service).check("c:\\Dir\\file.avi");
}

As you can see there is no design decision or interesting code to verify behaviour. I am testing values from view passed to MediaService. I usually write but don't like these kind of tests. What do yo do about these situations ? Do you write tests for all the time ?

UPDATE :

I have changed the test name and code after complaints. Some users said that you should write tests for the trivial cases like this so in the future someone might add interesting behaviour. But what about “Code for today, design for tomorrow.” ? If someone, including myself, adds more interesting code in the future the test can be created for it then. Why should I do it now for the trivial cases ?

1
  • 1
    "Some users said that you should write tests for the trivial cases like this so in the future someone might add interesting behaviour.But what about “Code for today, design for tomorrow.” ? " Brilliant rebuttal! +1
    – maple_shaft
    Commented Jun 22, 2011 at 12:34

7 Answers 7

5

I don't aim for 100 % of code coverage. And I usually don't write tests of methods which will obviously not contain any business logic and/or more than a few lines of code. But I still write unit tests (using TDD) of methods which not seem that complex. This is mostly because I like to have the unit test already, when coming back to that code months or even years later, and want to make it more complex. It's always easier to extend existing tests, than having to build it all from scratch. As Noufal said, it's subjective. My advice is to write the tests, if you think the method is a bit complex or have the potential to get more complex.

2

This is the second TDD question today that conveys annoyance at the number of tests to be written.

"Test it only if you would want it to work."

I'm not really sure I understand the test in the question.

Are you checking that Controller.Check() delegates to the service (dependency) with the argument as the selected file value from the view ? If yes, This is a good test. It allows you to test the controller without the actual service implementation. (interaction-based micro-tests).

Update: Now that I'm clear on what you're trying to test, I'd probably move some code around and rename a few things so that it reads "Test Media Controller delegates selected file check to media service." - which is a valid spec for the controller.

public class TestMediaController

@Test
public void DelegatesSelectedFileCheckToMediaService(){
    string selectedMediaFileInView = "c:\\Dir\\file.avi";

    when(_view.getSelectedFile).thenReturns(selectedMediaFileInView);

    new MediaController(_service, _view).check();

    verify(_service).check(selectedMediaFileInView);
}
6
  • Yes It delegates to the service class.
    – mcaaltuntas
    Commented Jun 22, 2011 at 7:17
  • But question: is it worth it to write this test to only verify parameter passed from view to service class?
    – mcaaltuntas
    Commented Jun 22, 2011 at 7:25
  • @Yes - it tests that check() is wired correctly. There should be another test that Service.Check() works once it receives the call. This test looks trivial today but as time goes on someone might add more code to this method (e.g. a guard clause if some-condition return;) and break existing behavior. This test safe-guards against that.
    – Gishu
    Commented Jun 22, 2011 at 7:41
  • 2
    @mcaaltuntas: the whole point of TDD is that you test the current specification, so that if a future code change no longer satisfies the current spec, you find out about it. No matter how easy you think it is to implement the spec now, someone might in future change the code without paying attention to this specific requirement, in which case they might break it and they won't realise they need to add a test for it. If you don't write the test now, then you are not doing TDD. If you don't want to test the whole spec, that's your call, but you aren't applying TDD to that part of it. Commented Jun 22, 2011 at 9:15
  • 1
    @mcaa - Whatever Steve said + you might set a precedent that it's okay to not write tests. The threshold of what is "interesting enough to test" might keep rising over time... The test above is not much of an effort.. it's hardly 5 lines and in return you get 95%+ peace of mind
    – Gishu
    Commented Jun 22, 2011 at 9:40
1

I wouldn't write a test like that (or at least I would not name it like that). Instead, I would write a test for the feature which requires that call to check(), so that if that check or an equivalent action is not done, the high-level feature would not work. Why does your code need to call the check() method?

In general, I try to keep the tests decoupled from the implementation details, so that at least the name of the test talks only about the external features provided by the object. Implementation details such as objects and methods are not mentioned in the test name.

This makes it easier to do refactoring (it shouldn't be necessary to change tests when you change the implementation) and it will also make it easier to find out whether a test is out of date (the feature it specifies is not anymore needed). It will also make it easier to notice unnecessary/dead code, because low-level boilerplate (such as getters and setters) will only be added/kept if they are required by higher level features.

7
  • Ok.You are right about naming you can think of its name "when user clicks check it should check selected file's properties" . But the question is not about naming Do you write tests for "obvious" code or not
    – mcaaltuntas
    Commented Jun 22, 2011 at 6:40
  • I have changed test name but question still remains.
    – mcaaltuntas
    Commented Jun 22, 2011 at 6:47
  • What should the system do, if that check fails? Throw an exception or something else? I would probably write two tests: what happens when the file is valid, and when it's invalid. If there are many ways a file can be invalid, I would write those tests directly against MediaService. Commented Jun 22, 2011 at 7:07
  • Yes Probaby I would write two tests too but not against Controller class I would write them against (like you said) MediaService class. So Actually the test only verifies service class has been called with parameters from view. Do you think is it worth writing this test to only verify arguments passed from view to service class ?
    – mcaaltuntas
    Commented Jun 22, 2011 at 7:22
  • "Do you think is it worth writing this test to only verify arguments passed from view to service class?" It depends. If there are end-to-end tests in place which make sure that check works (i.e. it gives an error message or something when the file is not valid), then for the controller's unit tests it might be enough to just check that the method is called; it would give faster protection during refactoring than the end-to-end tests. Commented Jun 22, 2011 at 10:04
0

This is subjective. I don't always do TDD but when I do, I try to keep code coverage as my metric for whether my tests are comprehensive or not. Sometimes, I get lazy and simply skip parts which to me seem "obvious". Sometimes, I violate the Red, Green, Refactor cycle and write more code than is necessary but over time, I've gotten into a rhythm than I'm comfortable with.

0

Interactions between classes like the above and the simpler original I would write a test for. Interactions can become more complex over time so having the ground work in place is a good thing.

0

If someone or I add more interesting code in the future I can create test for it then. Why should I do it now for the trivial cases?

You assume that in the future someone will know that this UI element exists and what it calls on the backend.

My current project has over 30 developers on six distinct teams inside the same code base. Trivial UI additions disappear into the fog all the time. No one will go back and add a test case for this later because no one will remember it is there and when it breaks the demand becomes "Why didn't they write a test? It would have been so simple!"

0

As usual...

It Depends

It's difficult to see the usefulness of this particular test in a TDD context because we don't know the story.

If the story is As a [media user] I want to [be able to check media validity] So that [I'll know when a file is not available]

then the scenario Given [a check media button] When [the user clicks the button] Then [the file validity is checked]

makes sense. It's trivial, but it makes sense.

If the overarching story is larger than this, then the scenario definition may be too narrow.

Remember:

TDD != Unit Testing

TDD tests features. If it's a feature, then it deserves a test to verify it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.