Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing : what to test / what not to test?

Tags:

Since a few days ago I've started to feel interested in Unit Testing and TDD in C# and VS2010. I've read blog posts, watched youtube tutorials, and plenty more stuff that explains why TDD and Unit Testing are so good for your code, and how to do it.

But the biggest problem I find is, that I don't know what to check in my tests and what not to check.

I understand that I should check all the logical operations, problems with references and dependencies, but for example, should I create an unit test for a string formatting that's supossed to be user-input? Or is it just wasting my time while I just can check it in the actual code?

Is there any guide to clarify this problem?

like image 275
Ed. Avatar asked Jan 24 '12 11:01

Ed.


People also ask

What Cannot be tested in unit testing?

Do not test anything that does not involve logic. For example: If there is a method in the service layer which simply invokes another method in the data access layer, don't test it.

What should be tested in unit testing?

Unit tests should validate all of the details, the corner cases and boundary conditions, etc. Component, integration, UI, and functional tests should be used more sparingly, to validate the behavior of the APIs or application as a whole.

Should you unit test everything?

The answer to the more general question is yes, you should unit test everything you can. Doing so creates a legacy for later so changes down the road can be done with peace of mind. It ensures that your code works as expected.

What can be mocked for unit testing?

What is mocking? Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies.


2 Answers

In TDD every line of code must be justified by a failing test-case written before the code.

This means that you cannot develop any code without a test-case. If you have a line of code (condition, branch, assignment, expression, constant, etc.) that can be modified or deleted without causing any test to fail, it means this line of code is useless and should be deleted (or you have a missing test to support its existence).

That is a bit extreme, but this is how TDD works. That being said if you have a piece of code and you are wondering whether it should be tested or not, you are not doing TDD correctly. But if you have a string formatting routine or variable incrementation or whatever small piece of code out there, there must be a test case supporting it.

UPDATE (use-case suggested by Ed.):

Like for example, adding an object to a list and creating a test to see if it is really inside or there is a duplicate when the list shouldn't allow them.

Here is a counterexample, you would be surprised how hard it is to spot copy-paste errors and how common they are:

private Set<String> inclusions = new HashSet<String>();
private Set<String> exclusions = new HashSet<String>();

public void include(String item) {
    inclusions.add(item);
}

public void exclude(String item) {
    inclusions.add(item);
}

On the other hand testing include() and exclude() methods alone is an overkill because they do not represent any use-cases by themselves. However, they are probably part of some business use-case, you should test instead.

Obviously you shouldn't test whether x in x = 7 is really 7 after assignment. Also testing generated getters/setters is an overkill. But it is the easiest code that often breaks. All too often due to copy&paste errors or typos (especially in dynamic languages).

See also:

  • Mutation testing
like image 129
Tomasz Nurkiewicz Avatar answered Oct 18 '22 23:10

Tomasz Nurkiewicz


Your first few TDD projects are going to probably result in worse design/redesign and take longer to complete as you are learning (at least in my experience). This is why you shouldn't jump into using TDD on a large critical project.

My advice is to use "pure" TDD (acceptance/unit test everything test-first) on a few small projects (100-10,000 LOC). Either do the side projects on your own or if you don't code in your free time, use TDD on small internal utility programs for your job.

After you do "pure" TDD on about 6-12 projects, you will start to understand how TDD affects design and learn how to design for testability. Once you know how to design for testability, you will need to TDD less and maximize the ROI of unit, regression, acceptance, etc. tests rather than test everything up front.

For me, TDD is more of teaching method for good code design than a practical methodology. However, I still TDD logic code and unit test instead of debug.

like image 36
Garrett Hall Avatar answered Oct 19 '22 00:10

Garrett Hall