How do I find what tests use this method?

As I said earlier, I’ve been reading Michael Feathers _Working Effectively With Legacy Code_ recently (I’m taking my time with it; it’s a good book). He spends a lot of time talking about techniques to get code under test. However, he spends very little talking about finding out if (and to what extent) a method is under test in the first place. So here’s how I do it:

  1. Start with working tests.
  2. Enable assertions when running your tests (worth doing all the time!)
  3. Start the method with assert false : "Forced test failure"
  4. Run all[1] your tests.
  5. The ones that break use the method.

Having identified the tests, you can inspect them to see which one (if any) is the right one to enhance to cover the new-or-changed functionality. Most important of all, you can inspect them to see what kind of changes you could make that wouldn’t cause test failures, because it’s those kind of holes in test coverage that can cause you to introduce bugs.

Now, it’s easy to say that, with TDD, you end up with good correlation between code and tests. If that’s the case, you simply open up FooTest, find all the methods called testBarXYZ() and away you go. In practice, you don’t end up with that tight a correlation. Here’s why:

  • First, you shouldn’t aim for a 1-1 correlation anyway. Your tests should focus on behaviour, and you’re betting off grouping by behaviour than by class. Grouping by class is convenient but shouldn’t be a constraint. It’s not hard to come up with reasons to have more than one test class for a given class (repeated, but different, setup code being the main driver), and there may be many classes which don’t have direct tests.
  • Second, even if you start with a 1-1 correlation, you don’t end up keeping it. When you refactor, it’s dangerous (and often not sensible) to move tests around. Thus, when you apply the Extract Method or Extract Class refactorings, you can easily end up with code units that aren’t directly tested. This is especially true with automated refactoring tools, but I’m sure it would happen if refactoring manually as well.

A side effect of this technique is to let you see how extensive the afferent coupling to the method really is; having a huge number of test failures would be a code smell indicating some sort of God class in many cases (utility methods excepted, but then utility methods don’t change that much either).

[1] Or a subset that runs fast.

Author: Robert Watkins

My name is Robert Watkins. I am a software developer and have been for over 20 years now. I currently work for people, but my opinions here are in no way endorsed by them (which is cool; their opinions aren’t endorsed by me either). My main professional interests are in Java development, using Agile methods, with a historical focus on building web based applications. I’m also a Mac-fan and love my iPhone, which I’m currently learning how to code for. I live and work in Brisbane, Australia, but I grew up in the Northern Territory, and still find Brisbane too cold (after 22 years here). I’m married, with two children and one cat. My politics are socialist in tendency, my religious affiliation is atheist (aka “none of the above”), my attitude is condescending and my moral standing is lying down.

5 thoughts on “How do I find what tests use this method?”

  1. Robert, I am confused as to the difference between what you have described and line based code coverage tools?

    Could those tools do what you want – or am I missing something?

  2. I don’t think I’ve seen a line based coverage tool that will tell me _what_ tests used a method; merely how many times the line was executed (which may or may not have a correlation to the number of tests)

    If there is one, please let me know. Maybe Agitar can do this.

  3. Hi Robert,

    I was going to suggest something like “Find Usages” in IntelliJ, or the equivalent in Eclipse, but I suspect you’re also worried about n-degree-of-separation usages where a test calls methodA, which in turn calls methodB, etc…

  4. Ah yes I get what you mean now.

    I saw a demo of Agitar, but I don’t remember them showing that specifically (but it wouldn’t surprise me if they did, there was a veritable trevor-trove of info that it spat out at various points). Not sure of the cost – if you have to ask, you probably can’t afford it.

    Maybe you could wrap aspects around every method call (not tests), and then with each test method being called in isolation you can see what methods lit up.

    I’ll get back to work now, and stop trying to dream up dodgy uses of aspects.

  5. Andy,

    You pretty much got the usage. Instead of wondering “what may I break if I change this”, find out by _forcing_ a breakage in every scenario. Then iterate over them.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: