Unnecessary Unit Tests
Find the English version below
Hi ,
Schon mal von tautologischen Tests gehört?
In den letzten Monaten habe ich mich wieder intensiv mit Testarchitektur und Testdesign auseinandergesetzt.
(Ich weiß gar nicht mehr, wie das angefangen hat... vermutlich wieder der YouTube Algorithmus, der interessante Vorträge vorgeschlagen hat 😉)
Jedenfalls habe ich Anfang Dezember schon darüber geschrieben, dass ich noch vor einigen Jahren in einem Blog ganz andere Praktiken propagiert habe, als ich heute empfehle.
Das Thema lässt mich nicht los, also geht es heute wieder um Tests.
tautological adjective
"using two words or phrases that express the same meaning, in a way that is unnecessary and usually unintentional"
Ein tautologischer Test entspricht der Implementierung - nur mit anderen Worten
Solche Tests lese ich immer wieder. Ehrlicherweise habe ich sie selbst viel zu lange geschrieben und nicht gemerkt wie sinnlos sie sind.
Aber schauen wir mal auf ein Beispiel:
Angenommen wir haben eine Methode die folgendes macht:
public void createOrder(UUID customerId, String orderName) {
Customer customer = customerRepository.findById(customerId);
Order order = orderFactory.createOrder(orderName, customer);
orderRepository.save(order);
}
Und der dazugehörige Test sieht folgendermaßen aus:
@Test
public void createOrderSavesTheOrder() {
Customer customer = new Customer("customerName");
String orderName = "orderName";
Order order = new Order(orderName, customer);
when(orderFactory.createOrder(orderName, customer)).thenReturn(order);
when(customerRepository.findById(customer.getId())).thenReturn(customer);
orderService.createOrder(customer.getId(), orderName);
verify(orderRepository).save(order);
}
Dann sehen wir einen klassischen tautologischen Test.
Wir drücken im Test die Implementierung aus - nur in andern Worten.
when(orderFactory.createOrder(orderName, customer)).thenReturn(order);
ist die gleiche aussage wie Order order = orderFactory.createOrder(orderName, customer);
in der Implementierung.
Ein solcher Test ist nicht nur sinnfrei - er verschlechtert die Maintainability des Codes
Ein solcher tautologischer Test erschwert es Entwicklern, die Implementierung zu refactoren.
Jede Änderung am Code (Ja, jede!) hat zur Folge, dass der Test angepasst werden muss. Und dabei muss sich nicht mal die Semantik ändern.
Der Test bringt keinen Mehrwert. Er ist nur im Weg.
Ganz ehrlich: Solche Tests kannst du direkt löschen. Fokussiere dich auf Funktionalität und nicht auf die Implementierung. Du musst Tests schreiben, die sehr konkrete (!) Ergebnisse testen. Deine Implementierung muss davon unabhängig sein.
Gute Tests schreiben erfordert Übung und Training. Hast du schon mal ein Coding Dojo veranstaltet und TDD geübt? Hast du das schon mal mit deinem Team gemacht?
Probier das doch mal aus. Und wenn du Hilfe dabei brauchst, dann melde dich bei mir!
Rule the Backend,
~ Marcus
Hi ,
Ever Heard of Tautological Tests?
In recent months, I've delved back into test architecture and design.
(I can't quite remember how it all started... probably the YouTube algorithm suggesting interesting talks again 😉)
Anyway, I wrote back in early December that a few years ago, in a blog, I propagated practices quite different from what I recommend today.
The topic keeps gripping me, so today, it's about tests again.
tautological adjective
"using two words or phrases that express the same meaning, in a way that is unnecessary and usually unintentional"
A Tautological Test Mirrors the Implementation - Just in Different Words
I keep coming across such tests. Honestly, I've written them myself for far too long without realizing how pointless they are.
But let's look at an example:
Suppose we have a method that does the following:
public void createOrder(UUID customerId, String orderName) {
Customer customer = customerRepository.findById(customerId);
Order order = orderFactory.createOrder(orderName, customer);
orderRepository.save(order);
}
And the corresponding test looks like this:
@Test
public void createOrderSavesTheOrder() {
Customer customer = new Customer("customerName");
String orderName = "orderName";
Order order = new Order(orderName, customer);
when(orderFactory.createOrder(orderName, customer)).thenReturn(order);
when(customerRepository.findById(customer.getId())).thenReturn(customer);
orderService.createOrder(customer.getId(), orderName);
verify(orderRepository).save(order);
}
Then we see a classic tautological test.
In the test, we're just rephrasing the implementation.
when(orderFactory.createOrder(orderName, customer)).thenReturn(order);
is the same statement as Order order = orderFactory.createOrder(orderName, customer);
in the implementation.
Such a Test is Not Only Meaningless - It Degrades Code Maintainability
A tautological test like this makes it annoying for developers to refactor the implementation.
Any change in the code (Yes, any!) results in having to adjust the test. And this doesn't even require a semantic change.
The test adds no value. It's just in the way.
Honestly: Such tests can be deleted right away. Focus on functionality, not implementation. You need to write tests that test very specific (!) results. Your implementation should be independent of this.
Writing good tests requires practice and training. Have you ever hosted a coding dojo and practiced TDD? Have you done it with your team?
Give it a try. And if you need help with it, just get in touch with me!
Rule the Backend,
~ Marcus