Is there a way to protect Unit test names that follow the MethodName_Condition_ExpectedBehaviour pattern against refactoring?

I follow the naming convention

MethodName_Condition_ExpectedBehaviour

when it comes to naming my unit tests, which test certain methods.

eg:

[TestMethod] public void GetCity_TakesParidId_ReturnsParis(){...} 

But when I need to rename a test method, tools like ReSharper do not offer me to rename those tests.

Is there a way to prevent such cases from occurring after renaming? How to change ReSharper settings or after a better module naming convention, etc.?

+6
source share
3 answers

The final pattern is group tests into inner classes by the method they test.

For example (excluding test attributes):

 public CityGetterTests { public class GetCity { public void TakesParidId_ReturnsParis() { //... } // More GetCity tests } } 

For more information, see Structuring Unit Tests from the Phil Haack Blog .

The best thing about this layout is that when you change the name of the method, you only need to change the name of the inner class, not just the individual tests.

+7
source

I also started with this conversion, but in the end I got the feeling that this is not very good. Now I am using BDD style names such as should_return_Paris_for_ParisID .

This makes my tests more readable and alsow allows me to rename method names without worrying about my tests :)

+1
source

I think the key here is what you should test.

You mentioned TDD in tags, so I hope we try to stick with this. In this paradigm, the tests you write have two goals:

  • maintain your code after writing it, so you can reorganize without fear that you broke something.

  • To guide us to a better way to design components . First, recording a test makes you think about what is needed to solve the problem.

At first I know that this question concerns the first point, but in fact I think about the second. The problem is that you have specific components that you are testing instead of a contract.

In terms of code, this means that I think we should test interfaces instead of class methods, because otherwise we subjected our test to a lot of problems associated with testing components instead of contracts - inheritance strategies, building an object here, renaming.

It is true that interface names will also change, but they will be much tougher than method names. What TDD gives us here is not just a way to support changes with a test harness - it makes it clear that we could be wrong about that!

Take for example the code you gave:

 [TestMethod] public void GetCity_TakesParidId_ReturnsParis(){...} { // some test logic here } 

And let's say we test the GetCity () method on our object, CityObtainer - when did I set this object? Why did I do this? If I understand that GetMatchingCity () is the best name, then you have the problem described above!

The solution I propose is that we think about what this method actually means earlier in this process, using the interfaces:

 public interface ICityObtainer { public City GetMatchingCity(); } 

Having written this style “outside the home”, we are forced to think about what we want from the object much earlier in the process, and it becomes a focus to reduce its volatility. This does not fix your problem, but can mitigate it a bit (and I think this is the best approach).

Ideally, we take one more step, and before starting the test we do not even write code:

 [TestMethod] public void GetCity_TakesParId_ReturnsParis { ICityObtainer cityObtainer = new CityObtainer(); var result = cityObtainer.GetCity("paris"); Assert.That(result.Name, Is.EqualTo("paris"); } 

Thus, I can see what I really want from the component, before I even start writing it - if GetCity () is not what I want, but rather GetCityByID () , this would have appeared much earlier in this process. As I said above, it is not reliable, but can slightly reduce pain for this particular case.

As soon as you go through this, I feel that if you change the name of the method, it is because you change the terms of the contract, which means that you must have come back and reviewed the test (since it is possible, you did not want to change it).

(As a quick add, if we are writing a test with TDD, then something happens inside GetCity () , in which significant logic happens. Thinking about the test since concluding the contract helps us to separate the intention from the implementation - the test will remain valid no matter what we will change behind the interface!)

0
source

Source: https://habr.com/ru/post/904524/


All Articles