Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing - What not to test

Tags:

unit-testing

People also ask

What should be tested in unit testing?

The purpose of a unit test in software engineering is to verify the behavior of a relatively small piece of software, independently from other parts. Unit tests are narrow in scope, and allow us to cover all cases, ensuring that every single part works correctly.

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.

Which is not true in case of unit testing?

Answer: It decrease the software development speed.


I'm not sure I can agree with any of the exceptions that you mention in your answer.

Methods not involving logic

Even if a method simply just delegates its implementation to an inner dependency, it is very relevant to verify that it happens. I presume that you write code for a reason, so you need to write a test that ensures that it stays that way.

Remember that one of the key benefits of unit tests are as regression test suites. Testing that an inner dependency is being correctly invoked is called Interaction Testing. Say that you have the following method:

public void Save(Entity entity)
{
    this.repository.Save(entity);
}

It is very important to test that the repository's Save method is being invoked with the correct input. Otherwise, some other developer could come along at a later date and delete that line of code and the regression test suite wouldn't alert you.

Remember: Simple things are not guaranteed to stay simple.

Not testing database operations

Do you find it inconsequential whether data is being persisted correctly in the database? If you really, truly, don't care, then you don't need to test it - otherwise you do.

If you don't test your database operations, how do you know that your data access component works?

I am not saying that you should test your ORM library, but you should test that it is being used correctly.

Not testing object in all layers

I'm not sure what you mean by this question, but if a field can be null, and this is a problem, you need to test what happens when it is, in fact, null - everywhere.

It is much more preferable, then, to design your API so that values are guaranteed not to be null.

Conclusion

You should test everything you can test. No exceptions. Simple things don't stay simple, and you need to be able to verify that code that once worked keeps working.

There are things (such as UI) that you can't unit test, and these should be abstracted away so that they contain as little logic as possible, but everything else should be tested.

Test-Driven Development (TDD) is the best way to ensure that this happens.


Don't test anything that can't fail.

But more to your points.

  1. This all depends on what you mean by logic. I took this approach on a mapping layer. I did not test all the boring code that copied property values from object A to object B. Bad copy paste and I had duplicated a copy and missed another. Big issue. But was it worth all the extra test code? Depends on what happens when the application fails. In this case it would have been worth the test code.

  2. Similar to point one. So Save is nice and simple, but how do you know you did the simple things right. Messing those up is just as bad as getting a bit of business logic wrong.

  3. You don't want to re-test things you already tested. But you should go beyond unit tests. Do integration and regression testing as well as unit testing. It's really nice when all the pieces work in a vacuum but blow up when put together.

Testing is a balancing act. If you truly test it all you might never get anything else done. But if you don't test it enough you spend all your time bug fixing. Where that balance point is changes. Different types of projects have different costs for failing. On some projects such as one that has understanding internal users you might be able to run loose and fast, but for how long? Eventually the untested code breaks, takes a while to find and you're not making any progress.

Best thing to do is follow true TDD. Don't test for testing's sake. Test as design technique. Test because it drives out loosely coupled code. Test because having code executed in two contexts (test and application) makes better code. Once you go down the path of TDD you don't ask what you should and shouldn't test. Testing just becomes part of writing code and not an independent activity.


Simple Answer - nothing

Complex Answer - you should not test things you do not have the time for. Testing is driven by a complex planning of the needed and affordable tests, prioritized for the most significant parts and workflows of the softwaresystem. The more time is left for testing, the more sidecases can be tested.

In UnitTesting is simply, every unit, in OOP every class has its own test. Test simply everything with values min, max, average usecases and do negativ tests - tests that have to fail if the software works correct. Test errorhandling as well.

See ITSQB for more details on that topic


Generally if possible I would go for a TDD style. This is very hard to achieve and needs a lot of discipline, but if you have it, you would never want to return. Btw, TDD is not just about testing, but more about software design (could also be called Test-Driven-Design). Your design evolves according to your tests.

Mark did give a quite good answer to your statements of what NOT TO TEST.

I don't need to validate objects at all layers. This means a certain field in an object should be not null, say the emailId in User Object, and this is verified and validated at the JSP(Using JS), I don't need to test how the DAL method behaves if it receives emailId=NULL, because ideally it should not, and this should be taken care by the JS.

In a layered application, it may happen that you have two kind of "front-ends" / entry points for your application. One may be the normal web user interface, another may be a web-service which is consumed by some other application (possibly a desktop application). Therefore all the logic related to validation should (also) be checked in the business layer (since validations may be part of the business logic).