16

Let's say there is a utility class that provides some common static methods used everywhere in your code by many other classes.

How would you design your unit tests for the consumers of the utility so that their tests fail if any one of the utility tests do not pass? Can you do it or do you have to check it yourself whether the utility class tests are all green?

For example I have a message-splitter utility that is used (or rather its output) by a message-parser. I'd like to be sure that the message-splitter works correctly before the message-parser gets tested.

I have written tests for both of them but is there a way to link them and make one test depend on the result of some other test?

I couldn't find a suitable tag for this but I'm using Visual Studio's unit test engine.

6
  • 1
    I understand that parser doesn't work correctly if utility fails. But if you run your tests you will see that utility tests fail. Why do you want other tests to fail also? Feb 27, 2015 at 10:00
  • 1
    I've never heard about anyone wanting this before. What are you trying to achive? Feb 27, 2015 at 10:05
  • 1
  • I use some of the utility functions to prepare data for the parser tests so I'd like to be absolutely sure the utility works correctly before I test anything else.
    – t3chb0t
    Feb 27, 2015 at 10:12
  • 3
    @t3chb0t If you want to ensure your utility works then you need to write unit tests to verify your utility. Unit tests should be atomic. You only ever want them to test a single component.
    – maple_shaft
    Feb 27, 2015 at 11:54

5 Answers 5

13

There is no point to making sure that every defect in your system trips exactly one test.

A test suite has one job: verifying that there are no known defects. If there is a defect, it doesn't matter if one test fails or 10. If you get used to your test suite failing, if you try to gauge how "bad" your program is by counting the failing tests, you're not using regression testing the right way. The test suite should pass all tests before you publish code.

The only valid reason for skipping tests is if they test incomplete functionality and take an inordinate amount of time that you could put to better use while implementing the thing they're supposed to test. (That is only an issue if you don't practice strict test-driven development, but that's a valid choice, after all.)

Otherwise, don't bother trying to make your test suite into an indicator telling you precisely what's wrong. It will never be exact, and it's not supposed to be. It's supposed to protect you from making the same mistake twice, that's all.

10

It depends on your tooling, but you probably can't (and shouldn't)

Some Unit-testing frameworks (take PHPUnit for example) allow you to 'chain' tests so that a failing test on one level does not execute other tests. However, I doubt that this will fix your problem for this situation.

Not allowing guaranteed test order execution forces tests to be isolated from each other and is generally considered a good thing. Imagine what would happen if tests would not only run themselves but also provide data for other tests to work on...

You can put these utility-methods in a separate solution or test-category. Make sure they visually 'stand out' in your test runner, or that this category runs first and does not run any other tests if the tests in this category fails*. When one of these tests fail the failure will probably cascade across all the tests and you should help make sure that whoever runs the tests knows to start by fixing these failing tests first of all. The same goes for Unit Tests and Integration Tests. If a Unittest fails, it will cascade and cause all sorts of mayhem in the Integration tests. Everybody knows that when Unit AND Integration tests fail, you start by checking out the Unittests...

*With an automated build or test script you could run this category first, check the result and only run the other tests if this first batch of tests pass.

5

Try keeping your unit test atomic. Remember that automated testing code is also part of your code base, but is itself not under test, so keep it as simple and obvious as possible.

To answer your question more directly, there is no guarantee of the order of executing of the tests so there is also no way to guarantee that your utility test succeeds before your other tests are run. So there is no guaranteed way to achieve what you want while still having a single test suite for all your tests.

You could move the utilities to their own solution and add a reference to its resulting dll in your current project.

5

I have the habit of always trying to differentiate application level code from framework level code, so I have encountered the problem that you are describing quite often: you usually want all the framework level code to be tested before any application level code begins to be tested. Also, even within framework level code, there tend to be some fundamental framework modules that are used by all other framework modules, and if something fails in the fundamentals, there is really no point in testing anything else.

Unfortunately, purveyors of testing frameworks tend to have somewhat rigid ideas about how their creations are meant to be used, and are rather protective of those ideas, while the people who use their frameworks tend to accept the intended usage without questioning. This is problematic, because it stifles experimentation and innovation. I don't know about everyone else, but I would prefer to have the freedom to try to do something in an odd way, and see for myself whether the results are better or worse than the established way, rather than not having the freedom to do things my way in the first place.

So, in my opinion, test dependencies would be an awesome thing to have, and in lieu of that, the ability to specify the order in which tests will be executed would be the next best thing.

The only way I have found to address the issue of ordering tests is by careful naming, so as to exploit the tendency of testing frameworks to execute tests in alphabetical order.

I do not know how this works in Visual Studio, because I have yet to do anything involving extensive testing with C#, but in the Java side of the world it works as follows: Under the source folder of a project we usually have two subfolders, one called "main", containing the production code, and one called "test", containing the testing code. Under "main" we have a folder hierarchy which exactly corresponds to the package hierarchy of our source code. Java packages roughly correspond to C# namespaces. C# does not require you to match the folder hierarchy to the namespace hierarchy, but it is advisable to do so.

Now, what people usually do in the Java world is that under the "test" folder they mirror the folder hierarchy found under the "main" folder, so that each test resides in the exact same package as the class that it tests. The rationale behind this is that quite often the testing class needs to access package-private members of the class under test, so the testing class needs to be in the same package as the class under test. In the C# side of the world there is no such thing as namespace-local visibility, so there is no reason to mirror the folder hierarchies, but I think that C# programmers do more or less follow the same discipline in structuring their folders.

In any case, I find this whole idea of allowing the testing classes to have access to package-local members of the classes under test misguided, because I tend to test interfaces, not implementations. So, the folder hierarchy of my tests does not have to mirror the folder hierarchy of my production code.

So, what I do is that I name the folders (meaning, the packages) of my tests as follows:

t001_SomeSubsystem
t002_SomeOtherSubsystem
t003_AndYetAnotherSubsystem
...

This guarantees that all the tests for "SomeSubsystem" will be executed before all tests for "SomeOtherSubsystem", which in turn will all be executed before all tests for "AndYetAnotherSubsystem", and so on, and so forth.

Within a folder, individual test files are named as follows:

T001_ThisTest.java
T002_ThatTest.java
T003_TheOtherTest.java

Of course, it greatly helps that modern IDEs have powerful refactoring capabilities which allow you to rename entire packages (and all sub-packages, and all code that references them) with just a couple of clicks and keystrokes.

1
  • 3
    I don't know about everyone else, but I would prefer to have the freedom to try to do something in an odd way, and see for myself whether the results are better or worse ++ mate. I don't know that I like the solution, but I like the attitude you've displayed there.
    – RubberDuck
    Jan 1, 2016 at 14:25
4

In a summary you don't want to use tools/techniques for doing things other than what they are meant for.

What you are trying to do sounds like a concern that could be solved easily with a CI (continuous integration) practice.

This way you can keep your tests atomic as already suggested and let the CI take care of verifying your tests.

If any tests fail you can set it so that it doesn't let your code to get published.

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.