Meine Antwort an diejenigen, die glauben, dass der Wert von TDD übertrieben ist

Einmal habe ich mit einem Entwickler eines Kundenunternehmens über Software gesprochen. Ich sollte verstehen, dass das Gespräch irgendwo schief gelaufen ist, als der Gesprächspartner sagte, wie wir als Softwareentwickler Glück hatten: „Wir bringen Organisationen dazu, uns für scheinbar einfache Arbeit zu bezahlen.“ Es spielt keine Rolle, wie weit jemand beim Schreiben von Code fortgeschritten ist, aber ich glaube, dass es sich nicht lohnt, über die gesamte Softwareentwicklungsbranche als eine Art Betrügerbande zu sprechen.

Ich habe mich nicht darauf konzentriert, das Gespräch kam zu Agile. Der Kunde war im Allgemeinen offen für die Idee, neue Methoden zu testen und seine Arbeitsprozesse zu verbessern. Aber - nur bis ich die Entwicklung durch Testen erwähnte (TDD, Test-Driven Development). Die einzige Antwort darauf war der folgende Satz: "Der TDD-Wert ist übertrieben."



Es war nicht nur schmerzhaft für mich, es zu hören, sondern es machte mir auch klar, dass TDD eine andere dieser agilen Methoden ist, die wie „urbane Legenden“ aussehen könnten. Deshalb habe ich dieses Material geschrieben, in dem ich diejenigen ansprechen möchte, die den Wert von TDD bezweifeln.

Was ist TDD?


Lassen Sie mich zunächst TDD definieren. Dies ist eine Softwareentwicklungsstrategie, bei deren Implementierung sie beim Erstellen eines Programms vollständig vom Schreiben von Tests geleitet werden. Tatsächlich ist dies aus dem Namen dieser Methodik verständlich. Diese Idee wurde von Kent Beck in seinem Buch Development Through Testing vorgeschlagen, das 2003 geschrieben wurde. Die Verwendung von TDD umfasst die folgenden drei Schritte:

  1. Schreiben eines Tests, der für eine kleine Funktionalität fehlschlägt.
  2. Implementierung der Funktion, die zum erfolgreichen Bestehen des Tests führt.
  3. Refactoring von altem und neuem Code, um ihn in einem gut strukturierten und lesbaren Zustand zu halten.

Dieser Prozess wird auch als "Rot, Grün, Refactoring" -Zyklus bezeichnet.

Hier ist ein einfaches Beispiel für die Verwendung von TDD. Hier wollen wir eine Methode in Python schreiben, die eine Variable Cnach dem Satz von Pythagoras berechnet .

Hier ist der Testcode (Datei test.py):

#!/usr/bin/env python

"""
test.py
"""

import unittest

from main import *

class TestDrivenDevelopment(unittest.TestCase):

        def test_pythagorean_theorem(self):
                a, b = 3, 4
                self.assertEqual(calculate_side_c(a, b), 5)

if __name__ == '__main__':
    unittest.main()

Hier ist der Methodencode ( main.py), in dem bisher nichts passiert:

#!/usr/bin/env python

"""
main.py
"""

def calculate_side_c(side_a, side_b):
    return True

Versuchen Sie nun, den Test auszuführen.


Der Test ist fehlgeschlagen (der "rote" Teil des TDD-Zyklus).

Schreiben Sie den Code neu und bringen Sie den Inhaltmain.pyin die folgende Form:

#!/usr/bin/env python

"""
main.py
"""

def calculate_side_c(side_a, side_b):
    c_squared = (side_a * side_a) + (side_b * side_b)
    c = c_squared ** 0.5
    return c 

Führen Sie den Test erneut aus.


Der Test verlief gut (der „grüne“ Teil des TDD-Zyklus).

Jetztmain.pyüberarbeitenwirdenCode:

#!/usr/bin/env python

"""
main.py
"""

def calculate_side_c(side_a, side_b):
    return ((side_a ** 2) + (side_b ** 2)) ** 0.5


Der Test war erfolgreich für den Code, der einem Refactoring unterzogen wurde (Teil „Refactoring“ des TDD-Zyklus).

17 Jahre sind seit der Veröffentlichung des Entwicklungsbuchs durch Tests vergangen. Aber auch heute, im Jahr 2020, gibt es noch keine endgültige Antwort auf die für viele Menschen sehr wichtige Frage, ob die Vorteile von TDD die Zeit und Mühe wert sind, diese Methodik umzusetzen. Infolgedessen versuchen viele Entwickler nicht einmal, sich durch Tests zu entwickeln.

Zur Unterstützung von TDD fragte ich Entwickler, warum sie diese Methode nicht verwendeten. Hier sind 4 Antworten, die ich am häufigsten gehört habe:

  1. Wir haben eine QS-Abteilung. Tests zu schreiben ist ihre Aufgabe.
  2. Das Erstellen von Tests, bei denen Moki und Stubs möglicherweise benötigt werden, kann viel Zeit und Energie in Anspruch nehmen.
  3. TDD hat keine Vorteile gegenüber der herkömmlichen Entwicklung.
  4. TDD ist langsam.

Lassen Sie uns diese Ideen analysieren.

Wir haben eine QS-Abteilung. Tests zu schreiben ist ihre Aufgabe


Diese Antwort auf meine Frage, warum jemand TDD nicht verwendet, bringt mich immer ein wenig zum Lachen. Ich bin ein großer Befürworter des Prinzips „ Sie bauen es, Sie führen es aus “, wenn derjenige, der den Code geschrieben hat, dafür verantwortlich ist. Daher stört es mich, wenn ich sehe, dass sich Entwickler so verhalten, als ob ihre einzige Aufgabe darin besteht, Funktionscode zu schreiben.

Ich bin zutiefst davon überzeugt, dass Entwickler dafür verantwortlich sind, dass ihr Code die folgenden Eigenschaften aufweist:

  • Korrektheit - Erfüllung der Geschäftsanforderungen.
  • Klarheit.
  • Testbarkeit.
  • Erweiterbarkeit.
  • Einfachheit.

Die Übertragung der Aufgabe, Tests zu schreiben, an die QS-Abteilung gehört meines Erachtens nicht zur Aufgabenliste des Entwicklers. Die Spezialisten der QS-Abteilung haben wichtigere Angelegenheiten. Sie sollten ihre Arbeitszeit nicht hauptsächlich damit verbringen, den Code mit der "Black Box" -Methode zu testen.

Das Erstellen von Tests, bei denen Moki und Stubs möglicherweise benötigt werden, kann viel Zeit und Energie in Anspruch nehmen


Ich verstehe die Gefühle derer, die das sagen. Beispielsweise müssen Sie eine Methode implementieren, die drei verschiedene Eingabewerte akzeptiert. Jedes von ihnen ist ein Objekt, und jedes dieser Objekte verfügt nicht über optionale Attribute. All dies muss getestet werden, indem die verschiedenen Optionen für die Methode überprüft werden. Dazu müssen Sie Stubs und Mokas konfigurieren und eine große Menge zusätzlichen Codes schreiben. Und das alles dient zum Testen nur einer Methode. Ich war schon in ähnlichen Situationen. Aber ich sehe das alles aus einer anderen Perspektive.

Wenn ich daran denke, den Aufwand und die Zeit für das Schreiben von Tests zu reduzieren, finde ich die Prinzipien der SOLID-Programmierung und die Testpyramide.

Beginnen Sie von hier aus mit SOLID .. An dieser Stelle möchte ich auf die Tatsache eingehen, dass SOLID in der Abkürzung durch den Buchstaben S dargestellt wird, dh nach dem Prinzip der alleinigen Verantwortung (Prinzip der Einzelverantwortung). Dies ist eine Idee, nach der Methoden und Klassen nur ein Problem lösen sollen. Sie müssen so funktionieren, dass ihre Aktivitäten den Rest des Systems nicht beeinträchtigen.

Ich verstehe, dass die meisten Methoden in Unternehmenssoftware Aufgaben ausführen, die schwieriger sind, als die Summe mehrerer Zahlen zu ermitteln, die an diese Methoden übergeben wurden. Man kann jedoch nicht leugnen, dass der Einsatz von Methoden zur Lösung eines Problems in einem Projekt das Testen erheblich erleichtert.

Lassen Sie uns über die Testpyramide sprechen.


Testpyramide (Bild von hier )

Die Testpyramide wird häufig verwendet, um das richtige Verhältnis verschiedener Testtypen in einem Projekt zu ermitteln.

Benutzeroberflächentests (UI-Tests) und Servicetests (Service-Tests) erfordern viel Zeit für ihre Implementierung. Daher sollte der Großteil der Tests durch Unit-Tests (Unit-Tests) dargestellt werden, da es Millisekunden dauert, um selbst eine große Anzahl solcher Tests auszuführen. Dies trägt natürlich dazu bei , die Rückkopplungsschleifezu verbessern , was eines der Hauptziele von DevOps ist.

Das Durchführen von Komponententests zum Testen eines kleinen Teils des Systems erfordert auch einen viel geringeren Integrationsgrad mit dem Rest des Systems. Dies erleichtert das Schreiben solcher Tests. Die TDD-Methodik ist ausschließlich für die Verwendung von Unit-Tests konzipiert.

Natürlich ist alles leichter gesagt als getan, und um die meisten Tests, auch Unit-Tests, zu schreiben, müssen Sie einige Anstrengungen unternehmen. Wenn es jedoch so aussieht, als ob das Schreiben eines Komponententests zu aufwändig ist, können Sie sich selbst testen, indem Sie sich einige Fragen stellen:

  • Handelt es sich um einen modularen Test oder sollte er als Test eines höheren Niveaus oder als Servicetest betrachtet werden?
  • Ist der Code gut gestaltet, entspricht jede Klasse und Methode dem Prinzip der alleinigen Verantwortung (ist der Code sehr eng miteinander verbunden)?

Wenn sich herausstellt, dass das Schreiben von Tests zu viel Zeit und Mühe kostet, deutet dies meistens darauf hin, dass der Code überarbeitet werden kann und wahrscheinlich muss.

TDD hat keine Vorteile gegenüber der herkömmlichen Entwicklung


Ironischerweise wird die Tatsache, dass TDD keine Vorteile gegenüber der herkömmlichen Entwicklung hat, hauptsächlich von jenen Programmierern gesagt, die nicht einmal versucht haben, im TDD-Stil zu arbeiten. Aber bis Sie etwas ausprobieren, können Sie nicht verstehen, ob dies gut oder schlecht ist. Sogar die Coldplay-Band weiß, dass "wenn du es nie versuchst, wirst du es nie erfahren".

TDD hat zwei Hauptstärken.

Der erste Vorteil von TDD liegt auf der Hand. Wenn vor dem Schreiben eines Arbeitscodes immer jemand Tests für diesen Code schreibt, verfügt der Programmierer per Definition immer über einen Selbsttestcode. Dazu schreibt Martin Fowler: „Sie haben einen Selbsttestcode, wenn Sie eine Folge automatisierter Tests auf Codebasis ausführen können, und nach erfolgreichem Abschluss der Tests können Sie sicher sein, dass der Code frei von signifikanten Fehlern ist.“

Mit anderen Worten bedeutet die Verwendung von TDD, dass der Code genau so funktioniert, wie es der Programmierer benötigt.

Dies ist eine wunderbare Tatsache, da sie bei nachteiligen Änderungen ernsthaftes Vertrauen in die Stabilität des Codes gibt. Durch die Verwendung von TDD kann der Programmierer sofort feststellen, ob sich etwas in der Codebasis infolge von Refactoring oder Erweiterung des Codes verschlechtert hat. Besser noch, es informiert Sie, wenn es Fehler im System gibt.

Selbsttest - Code ermöglicht Entwicklungsteams wirklich die Vorteile in Anspruch nehmen von Continuous Integration und Code - Deployment - Systeme .

Der zweite Hauptvorteil von TDD besteht darin, dass Programmierer bei dieser Entwicklungsmethode bereits vor dem Schreiben von Arbeitscode darüber nachdenken, was sie schreiben und wie sie ihn schreiben werden.

Das Überlegen des Codes vor dem Schreiben führt dazu, dass der Entwickler wirklich in die Essenz der Geschäftsanforderungen eintaucht und Grenzfälle und mögliche Schwierigkeiten bei der Implementierung geeigneter Mechanismen berücksichtigt. Infolgedessen wird beim Schreiben von Arbeitscode genau das aufgewendet, was Sie benötigen. Darüber hinaus führt der Einsatz von TDD dazu, dass Entwickler hinsichtlich ihrer Struktur und Architektur ein zukünftiges Gerätesystem planen. Wenn solche Dinge von Beginn der Arbeit an dem System an geplant und berücksichtigt werden, wird dies seine Fähigkeit zur Skalierung und Erweiterung erheblich verbessern.

TDD ist langsam


Entwickler, die sagen, dass TDD langsam ist, normalerweise diejenigen, die eine Weile mit dieser Methode gearbeitet haben und dann wieder Tests geschrieben haben, die ausgeführt wurden, nachdem der Code erstellt wurde. Im Allgemeinen ist dies der Grund, auf den am häufigsten Bezug genommen wird, wenn darüber gesprochen wird, warum jemand TDD nicht verwendet.

Ich kann auch verstehen, warum Programmierer so denken. Das Nachdenken über Code vor dem Schreiben braucht Zeit. Es wird Zeit aufgewendet, um Tests für alles zu erstellen, was implementiert werden soll, selbst für Methoden, für die unter normalen Bedingungen möglicherweise keine Tests geschrieben wurden. Manchmal ist es auch nicht die schnellste und angenehmste Aufgabe, Wege zu finden, um Stubs und Mobs effektiv zu nutzen.

Die Situation wird auch durch die Tatsache verschärft, dass die Produktivität und Effizienz von Programmierern häufig im Hinblick auf die Geschwindigkeit ihrer Arbeit und den Zeitaufwand für die Erstellung des fertigen Produkts bewertet werden. All dies treibt das Programmierteam zu dem Wunsch, so schnell wie möglich zu arbeiten, zu dem Wunsch, sich in die engen Arbeitspläne einzufügen.

In diesem Artikel wird das System der vier Indikatoren zur Bewertung der Wirksamkeit von DevOps beschrieben:

  1. Bereitstellungshäufigkeit.
  2. Ausführungszeit ändern.
  3. Wiederherstellungszeit des Dienstes.
  4. Die Häufigkeit von Fehlern mit Änderungen.

Ich interessiere mich besonders für die Indikatoren „Bereitstellungshäufigkeit“ und „Ausfallhäufigkeit bei Änderungen“.

Bei der Verwendung von TDD wird das Entwicklungsteam, wie bereits erwähnt, unter der Annahme, dass das System ausschließlich mit TDD erstellt wurde, unmittelbar nach einer Änderung des Systems feststellen, ob diese Änderung die Leistung eines Systems nicht beeinträchtigt hat von Teilen des Systems. Die Verwendung von TDD erhöht außerdem die Geschwindigkeit, mit der Fehler gefunden werden. Die Tatsache, dass die Tests darauf ausgelegt sind, sehr kleine Codefragmente zu testen, ermöglicht es Ihnen, sehr schnell den Ort des Projekts herauszufinden, an dem der Fehler aufgetreten ist. Dies führt dazu, dass Fehler in einer bereits bereitgestellten aktualisierten Version des Systems weniger wahrscheinlich erkannt werden, wodurch die Rate der „Fehlerrate bei Änderungen“ verringert wird.

Die Tatsache, dass das Entwicklungsteam ein hohes Maß an Vertrauen in die Nachhaltigkeit des Projekts und in seine korrekte Arbeit hat, bedeutet, dass das Team entscheiden kann, ob das Projekt bereitgestellt werden soll, wenn die Tests erfolgreich abgeschlossen wurden. Hat jemand die Projektbereitstellung bei Bedarf durchgeführt?

Das Phoenix-Projekt umfasst vier Arten von Arbeiten. Eine davon ist Unerwartete Arbeit. Solche Arbeiten müssen durchgeführt werden, wenn Entwickler sich von dem, was sie tun, ablenken und etwas anderes tun müssen. Normalerweise eine Korrektur eines Fehlers. Wenn das Projekt aus selbsttestendem Code erstellt wird, wird die Anzahl der Fehler minimiert. Dies führt wiederum zu einer Minimierung des „unerwarteten Arbeitsaufwands“. Und je weniger solche „Überraschungen“ im Leben des Entwicklers auftreten - desto besser fühlt er sich und desto produktiver und besser arbeitet er.

Wenn Entwickler sich weniger Gedanken über Fehler in der Produktion machen können, bedeutet dies, dass sie mehr Zeit für die Entwicklung neuer nützlicher Funktionen des Produkts verwenden können. Und wenn Entwickler im Voraus über den Code nachdenken, nützliche Prinzipien wie SOLID anwenden und sich ständig mit Refactoring befassen, wird die Höhe der „technischen Schulden“ minimiert. Wenn ein Team von der Funktionalität und Qualität des Codes überzeugt ist, kann es ihn buchstäblich in zwei Punkten bereitstellen. All dies erhöht die Arbeitsgeschwindigkeit.

Zusammenfassung


Wie jedes andere Tool, wie jeder andere Entwicklungsansatz, mag die TDD-Methodik zunächst unangenehm erscheinen. Und bevor Programmierer diese Methode richtig beherrschen, scheint sie ihnen etwas langsam zu sein. Was kann ich sagen? Um Jez Humble zu zitieren: "Wenn etwas Unbehagen verursacht, tun Sie es öfter und Sie können damit umgehen."

Und jetzt schlage ich vor, dass Sie die TDD-Methodik üben und dies tun, bis die TDD aufhört, Ihnen Unbehagen zu bereiten :)

Liebe Leser! Verwenden Sie die TDD-Methode, wenn Sie an Ihren Projekten arbeiten?

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


All Articles