DevOps Zone is brought to you in partnership with:

Yet another developer. Java, C#, C++. Aiming for Scala. Rado is a DZone MVB and is not an employee of DZone and has posted 12 posts at DZone. You can read more from them at their website. View Full User Profile

Sustainable Automated Testing

06.04.2013
| 6458 views |
  • submit to reddit

Unit testing over integration testing

Have you ever had a feeling that your automated tests are becoming overhead for the project? That the effort to keep them green seems to be higher than the added value? Then maybe what you do is integration testing and not unit testing.

I had the following discussion last week: “Do you have unit tests?”, “Sure. We do continuous delivery, unit tests are essential for us.” ...... “I’ve looked at your tests and I think that they are more integration tests than unit tests.”, “That’s just a matter of terminology. You know. Our application is heavily data-driven. There’s practically nothing to unit test. We must go to database.”

Hmm. Heavily data-driven. What does that mean? Isn’t every piece of software data driven? Ok, stop philosophising.

First of all, let’s make it clear what is typical for unit testing:

  • Don’t access database
  • Don’t access file system
  • Don’t depend on system time
  • Don’t access active directory
  • Don’t call external services
  • Don’t need real HTTP session to exist

This is not a definition of what unit test is. It’s rather a practical checklist. If you break any of these rules, your test is an integration test. That’s how I see it.

First problem is that integration tests need an environment to run. What’s worse, many of them need different environments. By environment I mean database, files, specific system time, session state, access permissions, … That’s a lot of work to do and maintain.

Second problem is that integration tests are not isolated. They don’t test one specific feature of one specific component. Their purpose is to validate that the whole flow through individual components works.

My intention is not to explain what integration testing is. What I would like to point to is that unit tests should not be replaced by integration tests. You’ll end up in hell where one small change in implementation will lead to many failed integration tests. To find out what is the real cause even of one failed integration test takes much more time than to fix a few unit tests. A lot more time. A unit test is focused to test one particular case of one specific method. If such unit test fails, it’s a piece of cake to find the reason.

How? Write classes that are (unit) testable. Let every dependency of a class to be an interface. Don’t be lazy, write interfaces. Once your class accesses the outer world though interfaces only, you are the winner. Then you can use techniques like stubbing and mocking. Writing and maintaining proper unit tests will not be a problem anymore. Long live heavily data-driven applications.
Published at DZone with permission of Rado Buranský, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Andreas Schilling replied on Tue, 2013/06/04 - 3:57am

Generating mock data to get rid of the database usually is the most tricky part, especially when you have a complex and highly normalized data model where properties of objects are usually other entities and not plain Strings and numbers as most examples show you (The world rarely consists of class Person with an assigned class Adress :-))

We found it helpful to have convenient builder-magic that is generated along with the entity classes (so it does not break upon model changes) and enables you to quickly write code to generate loads of testing data. That way we can quite easily (and reusable across test cases) feed the functions under test and, if those functions usually access the DB to get more data they need, mock away that DB access layer.

Any insight into your way of doing stuff like that? I'm always interested in other solutions as I find basically all examples on mocking/stubbing out there on the internets by far too simple constructed.

Molly Christiansson replied on Tue, 2013/06/04 - 9:56am in response to: Andreas Schilling

If you don't want to have a DB dependency, and you want to be able to test your "units", it's worth to have a look at the library that I'm using: https://github.com/EaseTech/easytest-core

This is actually an addition to jUnit with data driven facilities. Annotate your unit tests, prepare input data (e.g. csv / xls / xml) and run your tests. All the test data can be stored in the resources of your project and the unit test class remain very clean.

Rado Buranský replied on Tue, 2013/06/04 - 11:17am in response to: Andreas Schilling

That sounds nice. Although for testing you usually don't need just some data. You want to test how does the tested method behave in one specific case. For that you need the data to be set to specific values. I'm not sure if a generic generator can do that. But I can image that it can help you to do at least the hard work of writing a lot of lines of uninteresting code.

My experience is that I have created stubs and mock manually. Usually it's wasn't that hard and it could be reused by other tests as well.

Mohammed Hansen replied on Thu, 2013/06/06 - 4:53pm

if you'd like to see sustainable unit testing, as an integrated part of the end results, you might want to check out how magix integrates its unit tests in the final result, as a part of its output - http://code.google.com/p/magix-illuminate-2

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.