Wie man ein Auto dazu bringt, Tests aus Code für Sie zu schreiben

Wir leben in einer unvollkommenen Welt. Die Leute schreiben hier Code, und die Leute neigen natürlich dazu, Fehler zu machen . Alles wäre in Ordnung, Fehler können in der Testphase abgefangen werden und dürfen niemandem Schaden zufügen. Es ist möglich, wenn Sie Tests schreiben. Was die Leute aus irgendeinem Grund nicht gerne machen. Aber vielleicht gibt es Hoffnung - automatische Generierung von Tests aus geschriebenem Code.

Julia Volkova möchte die Idee in der Realität testen und versucht, die Erstellung von Tests basierend auf Code auf eine Maschine zu verlagern, ohne zusätzliche Anweisungen oder Verträge zu verwenden. Julia wird Ihnen über die Entdeckungen erzählen, die die Reise in die Welt der Metaprogrammierung, AST, Analyse und Tokenisierung bringt, und darüber, was all dies uns bei der automatischen Generierung von Tests bei Moscow Python Conf ++ ermöglicht hat. In der Zwischenzeit fragte ich, woher die Idee komme - das Testen zu automatisieren, was die Grundlage des Prototyps ist und was noch zu tun ist.

Julia Volkova (xnuinside) Senior Python Developer GridDynamics. pet-, . , legacy-, , . , «» . -, .

— , , , ? , . ?

- Ich denke, es gibt mehrere Gründe. Erstens sind die meisten von uns faul in der Natur. Nur wenige Leute schreiben direkt gerne Tests - wachen Sie morgens auf und sagen Sie: „Wir müssen den Tag mit 15 Tests beginnen, sonst wird alles schlecht, aber gleichzeitig wird mein Leben keinen Erfolg haben.“ Natürliche Faulheit manifestiert sich häufiger, insbesondere wenn Sie feststellen, dass die Methode nicht sehr interessant ist, einen klaren, primitiven Code enthält, Sie ihn jedoch noch mit Tests abdecken müssen.
Nur wenige schreiben TDD. Sie müssen also nicht nur einen Test schreiben, sondern auch Zeit mit dem Code verbringen.
Das Problem ist, dass nicht unendlich viel Zeit für die Entwicklung zur Verfügung steht. Es gibt immer zeitlich begrenzte Wunschliste-Produkte. In Produktteams war gestern in der Regel alles notwendig, denn Zeit ist Geld. Managern scheint, dass unser Produkt umso teurer und besser wird, je mehr wir eine Funktion begrünen. Und es ist nicht immer offensichtlich, dass das Testen der Abdeckung und der Codequalität sich direkt auf die nachfolgende Geschwindigkeit des Hinzufügens von Funktionen, der Codeunterstützung, der Aktualisierung usw. auswirkt.

Wir geben den Managern oft die Schuld und sagen, dass sie uns nicht genug Zeit geben, sonst würden wir sitzen und Tests schreiben. In der Tat ist dies nicht immer der Fall. Und nicht immer sagen erfahrene robuste Entwickler, dass sie Tests schreiben sollen, und jüngere Kollegen wollen das nicht.

Ich bin schon lange in der IT tätig, aber seit 3-4 Jahren direkt in der Entwicklung tätig. Davor habe ich mehr in Führungspositionen gearbeitet und verschiedene Entwickler gesehen. Es gibt viele Menschen, die nicht als unerfahren bezeichnet werden können, weil sie seit 10 Jahren Code schreiben, aber gleichzeitig glauben, dass Tests als solche nicht erforderlich sind. Angenommen, Sie müssen den Code nicht mit Komponententests abdecken, da es einen QS-Techniker gibt, der Fehler abfangen muss. Und sie glauben nicht, dass ein solcher Ingenieur nicht alle Fälle mit End-to-End-Tests abdecken kann.

"Wenn du nicht so extrem bist, was denkst du, wer sollte die Tests schreiben?" Sollte es der Programmierer selbst sein, der Junior oder umgekehrt der coolste Entwickler im Team?

- Wenn wir über Unit-Tests sprechen, sollte es definitiv keine Qualitätssicherung sein. Dies sollten auf jeden Fall die Tests sein, die vor dem Festschreiben überprüft, bestanden und geschrieben werden. Sie sollten angewiesen werden, eine Anfrage zu ziehen, in keinem Fall sollte eine andere Person sie später schreiben. Zum Beispiel würde ich als fauler Nicht-Junior-Entwickler nur Junioren dazu bringen, Tests für primitiven Code zu schreiben. Es gibt Dinge, für die es ausreicht, den Code einfach auf einer mittleren Ebene zu lesen und Behauptungen zu schreiben. Diese Arbeit ist für Junioren gut geeignet und für ihre Entwicklung nützlich.

Hierbei handelt es sich um Komponententests, die lediglich den aktuellen Statuscode abdecken. Diese Tests überprüfen nicht, wie gültig die Funktion in Bezug auf die Aufgabenanforderung in der Aufgabe ist, sondern stellen nur sicher, dass der Code das tut, was er tut und es richtig macht ...

Um jedoch die Gültigkeit des Codes für Geschäftsanforderungen und für die Geschäftslogik zu überprüfen, muss eine Person, die diese Anforderungen implementiert, dies dennoch tun. Er muss verstehen, was und wie er mit Tests abdeckt. Es ist jedoch nicht klar, wie es helfen kann, wenn eine Person das Problem anfangs nicht verstanden, eine Methode geschrieben hat, die es falsch löst, aber den richtigen Test für diese falsche Methode durchgeführt hat.

- Wir können sagen, dass das Problem darin besteht, dass die Leute eine schlechte Vorstellung davon haben, wie der Softwareentwicklungsprozess abläuft.

- Das ist sehr subjektiv. Sie stellen sich als eine Einheit von Entwicklern vor, die verstehen, dass Tests benötigt werden, warum sie benötigt werden, und Sie denken, dass dies wahr und gut ist. Es gibt jedoch eine ziemlich große Anzahl von Entwicklern, die glauben, dass dies überflüssig ist. In gewissem Sinne haben Manager wahrscheinlich auf ihre Weise Recht, wenn sie sagen, dass Tests nicht den gesamten Code abdecken müssen, sondern nur manuelle Tests auf der Bühne ausreichen.
Es ist nicht immer richtig zu sagen, dass eine Person, die Tests nicht mag, ein ungelernter Entwickler ist.
Er hat eine eigene Vision und ich kann sie nicht beurteilen. Ich treffe immer noch oft Entwickler, die seit 10 Jahren Code schreiben, und sage, dass es überflüssig ist, alles mit Unit-Tests abzudecken, genug Rauchtests und QS-Arbeit sind genug.

Ich fühle mich wiederum unwohl bei einem Projekt, bei dem es keine Unit-Tests für Funktionen gibt. Für mich ist es wichtig, dass es zumindest Tests gibt, die den Schutz vor dem menschlichen Faktor gewährleisten und in der Lage sind, ein zufällig platziertes Komma oder einen geänderten Schlüsselnamen in einem Diktat zu erfassen. Aber ich verbringe keine Zeit damit, weil ich immer mehr „kluge“ Aufgaben erledigen möchte. Daher denke ich über Tools zur Automatisierung des Schreibprozesses von Tests nach.

- Denken Sie, dass Python dynamisch typisiert ist und in der Kompilierungsphase nichts überprüft? Könnte es damit in anderen Sprachen einfacher sein?

- Ich denke, spielt und stark. Dies ist eine ewige Geschichte über Typen, aber mit dem Aufkommen von Typanmerkungen ist es einfacher geworden, damit zu arbeiten.

In Python kann es beispielsweise Ketten verschachtelter Funktionen geben, bei denen das am Ende der Liste erwartete aus irgendeinem Grund in ein Wörterbuch umgewandelt wird. Die Ausführung erreicht möglicherweise nie die endgültige Funktion, aber in einigen Fällen, wenn dies in Ausnahmefällen der Fall ist, wird ein Fehler angezeigt.

Bei einer getippten Sprache kann dies natürlich nicht grundsätzlich passieren, da bereits in der Kompilierungsphase ein Fehler auftritt. In dieser Hinsicht bietet Python natürlich zusätzliche Möglichkeiten, sich in den Fuß zu schießen (in den Kopf und anderswo). Insbesondere, wenn Sie mit großen Projekten mit verzweigter Logik arbeiten, bei denen Daten in verschiedene Variationen und in verschiedene Aggregationen eingegossen werden können.

- Was ist dann mit Typisierung? Denken Sie, dass das Tippen maximal oder minimal sein sollte? Wie sollte das Gleichgewicht zwischen der Eingabe von dynamischem Code sein?

- Das ist wieder ziemlich subjektiv. Viele Leute kamen zu Python, gerade weil es keine Eingabe gibt und weil alles so flexibel und bequem ist. Sie sollten dies nicht vergessen und nicht eine große Anzahl von Entwicklern aussortieren, einschließlich Datenwissenschaftlern und Analysten, die auch Code schreiben. Angenommen, ich als Backend-Entwickler fühle mich natürlich wohler, wenn das Tippen im Allgemeinen überall ist. Im Idealfall funktioniert mypy auch.

Bei den meisten Projekten, an denen ich teilgenommen habe, ist dies jedoch nicht möglich. Da das Projekt auch Datenanalysten hat, die sagen, dass sie in Python schreiben, weil sie sich nicht mit Typen herumschlagen möchten, ist dies für sie so praktisch.
Eine große Anzahl von Menschen glauben, dass plus Python in Abwesenheit von Typen und Typisierung.
Sie müssen bis zu einem bestimmten Grad wachsen, um zu verstehen, wann und warum es zu einem Minus wird. In einigen kleinen Python-Skripten oder in kleinen Projekten verwende ich auch keine Typen, da ich weiß, dass in einem Skript mit zwei Funktionen Typen nicht besonders benötigt werden. Aber das ist etwas, was ich grob gesagt schnell auf meinem Knie getan habe, um etwas aus der Basis herauszuziehen. Und in größeren Projekten versuche ich, überall Typen maximal hinzuzufügen, wenn andere Entwickler keinen Widerstand leisten.

- Da stimme ich Ihnen voll und ganz zu. Es bleibt nur zu verstehen, wie Typen verwendet werden, da dies ein separates, obskures Thema ist.

: «, Haskell , : , . Python , , ».

— . , , legacy- smoke-. . ?

- Ich werde nicht sagen, dass mein Ansatz besser ist, es ist einfach anders. Es ist gut, wenn Sie Ihren Code mit Rauchtests abdecken, wenn Sie können. Mein vorheriges Projekt war der Inbegriff von Schmerzen, die mit Tests verbunden waren. Es war eine datenwissenschaftliche Plattform mit 8 Microservices und 20.000 Codezeilen. Das Problem ist, dass die Plattform eine große Menge an Daten und Merkmalen für Fahrzeuge, Bahnhöfe und Städte, verschiedene Parkplätze und Arten von Verbrauchsmaterialien erhält, aggregiert und eine Vielzahl potenzieller Zeitpläne für diese Fahrzeuge auf der ganzen Welt erstellt. Der Zeitplan berücksichtigt eine Vielzahl von Bedingungen aus der Kategorie, unter denen Sie das Fahrzeug tanken und einen Zwischenstopp einlegen können.

Es gibt viele verschiedene Methoden im System, die in 1-2 Situationen verwendet werden können, an die sich vielleicht auch keiner der Clients jemals erinnern wird. Das Schreiben von Rauchtests wird dann tatsächlich zum Schreiben von Tests für das gesamte System, wobei alle Funktionen und ihre Kombinationen berücksichtigt werden.

Der Rauchtest sollte überprüfen, ob alles am Ausgang funktioniert und nicht minimal bricht. Ein sehr primitiver Rauchtest, den das System gestartet hat und der irgendwie funktioniert, bringt in unserem Fall keinen Nutzen. Angenommen, wir haben überprüft, ob eine Verbindung zur Datenbank besteht, etwas startet, die Benutzeroberfläche erhält eine Art API. Und dann einen Schritt nach links, einen Schritt nach rechts - und nichts funktioniert. Das heißt, es gibt sozusagen einen Rauchtest, aber Fehler fliegen immer noch aus der Produktion.

In diesem System haben Unit-Tests einwandfrei funktioniert: Wenn klar überwacht wird, dass sich die Funktionen nicht geändert haben, sind sie nach einigen Codeänderungen nicht fehlerhaft. Der Code ist auch anders. Unterschiedliche Projekte, unterschiedliche Aufgaben erfordern unterschiedliche Testansätze.

Die Idee, an der ich gerade arbeite, kann nur bedingt als automatische Generierung von Tests bezeichnet werden. Es ist eher ein Entwickler-Tool. Ich möchte ein Tool erhalten, das Tests für mich schreibt und den gesamten Code ausführt, der ohne mich ausgeführt werden kann.

Ich werde ein Beispiel geben. Es gibt eine kleine Funktion, die ein Wörterbuch übernimmt, aus dem ein Wert und ein Schlüssel stammen. Dieser Schlüssel ist für Unternehmen sehr wichtig, aber aus Sicht des Codes handelt es sich um eine eher primitive Operation: Nehmen Sie aus dem Wörterbuch, auch wenn es sich mehrmals um einen verschachtelten Schlüssel handelt. überprüfe, ob er da ist, dass er nicht Null ist; Tauschen Sie es aus oder geben Sie einfach den Wert zurück. Dies ist genau aus Sicht von AST ein ziemlich primitiver Code. Ich möchte meine Zeit nicht mit ihm verschwenden und Tests schreiben. Ich möchte, dass das Auto das für mich erledigt.

Dies ist genau ein Metaprogramm mit einem Eingabecode und einem Ausgabecode. Sagen Sie zum py-Modul, das sagt: "Hier habe ich eine Behauptung, ich habe Sie" unterstützt ", dass es in diesem Zustand Fehler gibt, gültige Werte in einer solchen Situation zurückgegeben werden, etwas anderes ist mit einem solchen Argument passiert." . Das heißt, es erledigt die Arbeit, bei der ich mir selbst ansehen würde, was dem Eingang der Funktion zugeführt wird, und es in den Test schreiben würde.

Ich möchte, dass das Programm das Minimum generiert, das es selbst für mich ausführen kann. Dies sollte jedoch eine Testdatei sein, in der Sie dann bei Bedarf etwas ändern oder erweitern können. Was Sie in Git, Test Test usw. festschreiben können.

- Wie sehr können Sie sich auf solche automatisch generierten Tests verlassen? Was meine ich - wie stark sind sie an eine bestimmte Implementierung gebunden und wie verhalten sie sich bei normalen Änderungen der Geschäftslogik oder beim Refactoring?

- Die Idee ist, den Code in der Form zu nehmen, in der er jetzt ist, und darauf basierend gültige Tests zu generieren.

Natürlich können Sie die Tests jedes Mal neu generieren, aber dies ist nicht korrekt, da dann keine Verfolgung des Status der Codeänderung erfolgt. Dementsprechend gibt es hierfür immer noch Testunterschiede, dh Tests werden nur für das generiert, was zuvor noch nicht durch Tests abgedeckt wurde. Und bereits erstellte Tests müssen von Ihnen selbst unterstützt werden.

Vielleicht ist dies eine kleine Paranoia, aber bisher bezweifle ich, dass mit der automatischen Generierung garantiert werden kann, dass Sie durch die Regeneration der Tests keinen gültigen Code mit gültigen Tests abdecken. Es ist eine Sache, wenn ich im Februar 2019 Tests generiert habe. Wenn Sie die Logik ändern, ändern Sie die Tests selbst, weil Sie wissen, welche Änderungen vorgenommen wurden. Sie wissen, warum die Tests gefallen sind, und können die Tests entsprechend korrigieren. Und es ist eine ganz andere Sache, wenn Sie sie jedes Mal regenerieren. Tests sind gültig, jedoch nur bis zu diesem geänderten Status des Codes.
Ich möchte ein Tool für den Entwickler und kein Tool zur Erhöhung der Codeabdeckung.

- Was können Erfolgsmetriken sein? Wie kann man verstehen, dass wir Tests gut generiert haben?

Ich werde benennen, worauf ich achte, ohne das mir die Tests keinen Sinn ergeben. Es ist unbedingt erforderlich, dass alle vom Entwickler beschriebenen Fälle von Codeverhalten in den Tests verarbeitet werden. Wenn es beispielsweise ein if gibt, das nichts zurückgibt, sondern ein Protokoll schreibt, sollte dieses Protokoll im Test funktionieren. Nicht nur, dass Leute Warnungen schreiben und drucken. Wenn irgendwo eine Verarbeitung von Auslösefehlern auftritt, müssen Sie diese in einem Test ausarbeiten. Wenn das Erhöhen plötzlich verschwindet, dh die Logik des Codes geändert wird, muss dies ebenfalls ausgearbeitet werden.

Wenn if-Anweisungen vorhanden sind, muss in ähnlicher Weise jede Bedingung verarbeitet werden. Dann wird der Test mehr oder weniger der Wahrheit nahe sein. Und vergessen Sie nicht, dass dies alles gestartet werden sollte und nicht nur „Erfolg“ in PyTest mit leeren Testkörpern.

- Sag mir, wie schwierig es technisch ist. Klingt nach einer ziemlich schwierigen Aufgabe.

Ja, dies ist eine sehr schwierige Aufgabe, und es ist wahrscheinlich diese Tatsache und einige andere Umstände, die mich veranlasst haben, in einem Bericht über Moscow Python Conf ++ darüber zu sprechen . Ich möchte dieses Thema ansprechen, andere Menschen dafür interessieren und mit ihnen Lösungen diskutieren.

Ich habe das Gefühl, dass niemand versucht hat, dies zu tun, weil die Aufgabe schwierig ist. Andernfalls würde es im Netzwerk einige Artefakte geben, wie Code, Beschreibungen, Artikel oder zumindest Erwähnungen, dass es so etwas gibt, aber es wurde aufgegeben.

Um zu verstehen, wie schwierig dies ist, erinnern wir uns daran, wie der Interpreter funktioniert. Es gibt Operationen, Anweisungen im Code, die der Interpreter ausführt - gut, nicht gut, fehlgeschlagen, nicht fehlgeschlagen - und das Ergebnis erzeugt. Außerdem fügt der Entwickler manuell neue Argumente hinzu, startet den Interpreter erneut und stellt sicher, dass jetzt alles erfolgreich ist. Wenn Sie jedoch versuchen, Tests für den Code zu generieren, müssen Sie zuerst den AST-Baum durchgehen und verstehen, welche Schritte Sie ausführen müssen, um das Ergebnis zu erhalten.

Eine Funktion kann viele Gruppen von Argumenten, Strategien für Argumente und viele Ergebnisse für diese Strategien haben. Apropos Strategien, ich meine, sagen wir, es gibt if arg_1==1: raise error. Dies bedeutet, dass es einige Gruppen gibt, arg_1=1für die die Funktion immer einen Fehler zurückgibt. Aber mit dem Argument wird das arg_1>2Ergebnis der Funktion anders sein und eine zweite Gruppe wird erstellt, die zweite Strategie.

Dementsprechend müssen wir alle diese Gruppen von Argumenten finden und hervorheben (falls dies natürlich der Fall ist), in denen die Funktion ihr Verhalten ändert. Und dann folgen Sie der Aktionskette: Was passiert innerhalb der Funktion mit diesen Argumenten, um das Endergebnis zu erhalten?

Darüber hinaus vergessen wir nicht, dass es neben der Tatsache, dass es einige Argumente gibt, auch Aktionen innerhalb der Funktion gibt, z. B. Variablen zuweisen und andere Funktionen aufrufen. Das heißt, wir erhalten auch ein Diagramm der Abhängigkeiten der Methoden von den Methoden, wenn Sie zum Überprüfen eines Codes zuerst das Ergebnis eines anderen Codes abrufen müssen.

Dementsprechend müssen Sie zum Generieren von Tests zuerst alle erforderlichen Informationen aus dem AST-Baum abrufen und dann Argumente, Parameter und Daten für jede Strategie generieren. Gehen Sie mit ihnen die gesamte Aktionskette durch, erhalten Sie das Ergebnis, und erst dann haben wir einen gültigen Test mit verschiedenen Behauptungen. Dies ist eine schwierige Aufgabe.

Ich glaube nicht, dass es eines Tages möglich sein wird, alle Arten von Fällen automatisch zu 100% abzudecken, zum Beispiel für die riesigen Leinwände mit Django-Quellcodes. Es ist mühsam, aber interessant. Bisher bin ich nur neugierig, wo ich die Geduld und Kraft habe, um zu erreichen.

- Gibt es Beispiele aus anderen Sprachen und Bereichen, in denen so etwas funktioniert?

- Es sind keine ähnlichen bekannt. Ich denke, weil es einfacher ist, einen Test zu schreiben, als ein Spezialwerkzeug zu schneiden.
Aber ich habe das Gefühl, dass wir früher oder später automatisieren werden, was wir bereits gut machen.
Es gibt einen großen Pool von Entwicklern, die Unit-Tests gut schreiben. Wir haben genug Kompetenzen in der Python-Entwicklung, um ein Tool oder eine Bibliothek schreiben zu wollen, die dies für uns erledigt. Und wir werden komplexere Dinge schreiben, komplexere Tests.

Es gibt eine Art Testgenerierung in Java, C und .Net. Aber auch dort ist alles eher immobilien- oder vertragsbezogen. In C gibt es eine Testgenerierung nach Zeichen, es scheint, als würde nur der Code betrachtet und auf dieser Grundlage werden einige Tests durchgeführt. Dies ist jedoch eine so unterschiedliche Abstraktionsebene in der Sprache selbst, dass ich nicht sicher bin, ob dies eine ähnliche Geschichte ist.

Wenn es etwas sehr Ähnliches gäbe, könnte man natürlich etwas übernehmen, guck mal.

- Denken Sie, dass Frameworks oder vielleicht Techniken zum Schreiben von Python-Code die Aufgabe des Generierens von Tests aus dem AST-Baum vereinfachen oder erschweren?

- Es ist schwer zu sagen, ob es in diesem Sinne sehr unterschiedlich ist, einfach eine Bibliothek zu importieren oder ein direkt spezifisches Framework zu verwenden. Absolut, es kann die Arbeit von etwas, das das Verhalten der Interpretation eines Codeprozesses ändert, beispielsweise einer C-Erweiterung, erheblich erschweren. Wie ich damit umgehen soll, weiß ich noch nicht, aber die Verwendung meiner bevorzugten dritten Pakete in diesem Problem beruht auf der Notwendigkeit, Importe aufzulösen. Mit integrierten Paketen ist alles einfach, aber mit Importen wird alles komplizierter. Mypy hat einige Ideen und Implementierungen, aber ich gehe noch nicht auf die Geschichte des Imports von Paketen von Drittanbietern ein.

- Vielleicht ist es eine Art Technik - viel Dynamik, die Verwendung von getattr - so etwas? Oder funktioniert es gut?

"Es funktioniert einfach perfekt." Weil getattr oder Manipulationen mit Metaklassen in AST sichtbar sind. Ja, sie müssen gelöst werden, was die Komplexität erhöht. Dies wird aber trotzdem verfolgt.

- Wir haben bereits gesagt, dass automatisch generierte Tests in erster Linie für Menschen gedacht sind. Wie lesbar werden sie für Menschen sein? In jedem Test steckt viel Logik, behaupten Sie? Wie wird die Trennung zwischen Code und Daten aussehen, wie sehen Sie das?

- Jetzt versuche ich zunächst, den Tests alle möglichen banalen Dinge hinzuzufügen. Angenommen, dies ist eine Art Erhöhungsfehler, dann ist es nicht nur eine Erhöhung, sondern hinterlässt zumindest einen Kommentar, welche Art von Fehler, warum er auftaucht, damit die Person nach dem Lesen des Tests versteht, was tatsächlich passiert ist, welches Argument zu welchem ​​Fehler führt .

Bisher in einer Methode kombinierte Behauptungen. Das heißt, wenn es eine Funktion gibt und es 5 Zustände gibt, die wir überprüfen möchten, dann gehen 5 Asserts in die Funktion.

Es gab die Idee, Namenskonventionen einzuführen, zum Beispiel: Fehler am Ende des Fehlers setzen, Testprotokolle haben auch etwas Eigenes. Aber ich habe es vorerst verschoben, weil die Frage, wie die endgültige Art von Tests im Code erstellt werden soll, direkt ein Textblock mit Tests, die kostengünstigste Operation ist. Wenn plötzlich die Idee auftaucht, dass alles neu formatiert werden muss, ist dies einfach - es gibt fertige zusammengesetzte Asserts, Sie müssen nur einen anderen Look für die Tests wählen.

- Unterstützen Sie Unittest oder Pytest?

- Pytest. Und nur weil ich jetzt nicht viel Energie für die Ausgabe aufwenden möchte. Pytest ist gut, weil es viele Plugins, Dekoratoren und verschiedene Modifikatoren gibt, die einfach zu bedienen sind.

Hübschheit kann sowohl für den Endbenutzer als auch für den Entwickler wichtig sein. Dies hat jedoch keinerlei Einfluss auf die Entwicklung der Idee. Wenn Sie unittest unterstützen müssen, kann dies einfach hinzugefügt werden.

- Inwieweit hängt dieser Ansatz mit eigenschaftsbasierten Tests zusammen?

- Um Argumente zu generieren, wird nur der Moki-Typ verwendet: Sie benötigen int, geben zufällige int. Solche Strategien lassen sich dann aber leicht umschreiben, beispielsweise mit der Verwendung von Hypothesen. Ich verbringe zwar nicht viel Zeit und Mühe damit, weil ich verstehe, dass ich dann Generatoren von Drittanbietern für den Wert verwenden kann. Nun, es scheint mir, ist dies nicht so wichtig wie die Arbeit mit AST.

- Planen Sie, die Vertragsprogrammierung zu unterstützen oder sich auf besondere Weise zu trennen? Weil es bei der Arbeit mit Unit-Tests, eigenschaftsbasierten Tests und Tests im Prinzip sehr hilfreich ist, um die Geschäftslogik zu verstehen.

- Wenn wir unter Vertragsprogrammierung Verträge im Code verstehen, dann weiche ich so weit wie möglich davon ab. Denn wenn Sie die Vertragsprogrammierung verwenden können, können Sie die Verträge grundsätzlich mit Verträgen codieren und auf deren Grundlage Komponententests generieren. Und dann wird mein Werkzeug nicht so gebraucht.

Jetzt versuche ich an nichts zu denken, was den Code verändert. Denn zum Beispiel bei Outsourcing-Projekten, bei denen ich mit dem Problem des Mangels an Tests konfrontiert war - und dies waren leider fast alle Projekte im aktuellen Unternehmen -, war es fast unmöglich, den Code zu berühren. Das heißt, es war unmöglich, Änderungen vorzunehmen, bis Sie garantieren konnten, dass dieser Dekorateur oder Vertrag nicht die gesamte Funktionskomponente des Codes ändert.
Wenn es möglich ist, den Code zu bearbeiten, sind Vertragstests gut.
Aber im Moment gehe ich davon aus, dass es keine solche Möglichkeit gibt. Auf diese Weise können Sie auf der Grundlage von Verträgen Komponententests erstellen und tatsächlich doppelte Funktionen implementieren.

- Erzählen Sie uns von dem nächsten wichtigen Punkt: Wie testen Sie die erhaltenen Tests und wie viel können Sie garantieren, dass diese Tests wirklich etwas testen?

- Mutationstests wurden nicht abgesagt, und in einem idealen Bild der Welt muss sie sicherlich in dieser Geschichte verwendet werden. Die Idee als Ganzes ist die gleiche, als ob der Test vom Entwickler manuell geschrieben worden wäre. Das heißt, alles, was zum Testen von Tests verfügbar ist, kann vollständig angewendet werden.

- Lassen Sie uns nun die Moscow Python Conf ++ Konferenz ein wenig diskutieren. Wir werden auftreteneiner der Hypothesenentwickler, die wir mehrmals erwähnt haben. Was würden Sie interessieren, um ihn zu fragen?

- Es würde mich interessieren, Zach zu fragen, wo sie das Projekt zusammen mit den Betreuern entwickeln möchten: was hinzuzufügen ist, wie zu entwickeln ist. Ich weiß mit Sicherheit, dass Zach jetzt eine PR für die Testgenerierung hat. Sie machen es regelmäßig. Genauer gesagt ergänzen Dekorateure bestehende Unit-Tests.

Ich möchte die Ideen der automatischen Testgenerierung dahingehend diskutieren, wie die Hypothese sie sieht, wie die Mitwirkenden sie sehen. Sicherlich haben Leute, die sich auf einem solchen Niveau mit Tests beschäftigen, einige Ideen oder vielleicht hat jemand bereits etwas ausprobiert.

„Wir zählen darauf, wenn wir das Konferenzprogramm vorbereiten: damit die Berichte Themen zur Diskussion stellen, bei denen jeder neue Ideen und Entwicklungsrichtungen finden würde. Zu welchen Berichten werden Sie gehen?

- Ich möchte mich aufregen und um 12 Uhr zu allen Berichten gehen. Zu diesem Zeitpunkt gibt es Zac Hatfield-Dodds, Andrey Svetlov mit einem Bericht über asynchrone Programmierung und Vladimir Protasov mit Refactoring-Automatisierung . Ich gehe zu einem der letzten beiden und renne dann am Ende des Berichts zu Zach ( Anmerkung des Herausgebers: Nehmen Sie einen Life-Hack in Betrieb - hören Sie sich das neue Thema fast vollständig an und kommen Sie zum Ende des Berichts und stellen Sie Fragen an den Redner, mit dem Sie sprechen möchten ). .

Es muss sehr interessant seinBericht über Datenvalidierung , ich bin direkt daran interessiert. Und es gibt zwei weitere Berichte, zu denen ich auch gehen würde, aber sie werden alle parallel zu meinen gehen: Dies ist ein Bericht von Vitaly Bragilevsky über das Tippen und Christian Heimes über das Profilieren . Leider kann ich sie in keiner Weise erreichen.

- Erzählen Sie mir etwas mehr über das Thema Ihres Berichts, warum tun Sie, was tun Sie, warum sprechen Sie und worauf warten Sie in der Rede?

- Ich möchte mehr Tools zur Automatisierung von Entwicklungsprozessen und mehr damit verbundene Kooperationen. Es gibt solche Aktivitäten, aber vor dem Hintergrund, ständig denselben Code zu schreiben, scheint es mir, dass es mehr geben sollte.

Wie gesagt, es gibt keine offenen Erfahrungen mit der automatischen Generierung von Tests in Python. Es ist unklar, ob jemand dies tat, wenn ja, warum nicht abhob, nicht ging. Ich weiß nicht, wie wichtig die Generierung von AST-basierten Tests für die Community sein wird und wie weit sie gehen kann. Jetzt mache ich das, weil ich am Prozess selbst interessiert bin, daran interessiert bin, durch AST-Bäume zu graben, mehr über die Funktionsweise von Python-Code zu erfahren und auf viele verschiedene Nuancen zu stoßen, die bei der Arbeit mit dem Code der obersten Ebene nicht offensichtlich sind. Die Arbeit mit AST-Bäumen bringt eine Menge plötzlicher Entdeckungen mit sich.

Ich möchte, dass die Leute nach dem Bericht Ideen haben, zum Beispiel, wie sie etwas automatisieren können, das sie in ihrer Arbeit verwenden. Damit einige von ihnen aufhören, Codeteile zu schreiben, die sie bereits jeden Tag schreiben, und beginnen, die Zeit zum Schreiben zu generieren oder zu verkürzen. Ich hoffe, jemand hat ein neues Verständnis dafür, wie dieses Problem gelöst werden kann.

- Wo nehmen Sie sich Zeit, um auf Konferenzen zu sprechen und Ihre eigenen Bibliotheken zu schreiben? Diese Frage taucht tatsächlich ständig auf. Viele Menschen beschweren sich, dass sie für nichts Zeit haben.

- Erstens über die Zeit. Ich bin für viele Unternehmen kein sehr bequemer Mitarbeiter in dem Sinne, dass ich keine Dinge tue, die mir unwirksam erscheinen. Ich versuche Dinge zu tun, die entweder für mich wirklich interessant sind oder die ich effektiv und richtig machen kann. Wenn der Manager zum Beispiel möchte, dass ich gerade einen Fehler behebe, der eigentlich kein Fehler ist, sondern die Wunschliste eines neuen Kunden, setze ich mich nicht hin und behebe alles zurück, weil ich weiß, dass der Kunde zurückkommt und sagt, warum Sie erledigt.
Ich versuche, keine unnötige Arbeit bei der Arbeit zu verrichten, nicht das zu tun, was den Verlust meiner Zeit danach zur Folge hat.
Angenommen, wenn sie mich am Freitag zum Einsatz auffordern, sage ich: „Leute, ich liebe euch alle sehr, ihr seid alle großartige Leute, aber wenn ihr jetzt etwas bereitstellen müsst, setzt euch bitte selbst ein, und ich werde nach Hause gehen. Ich kann es am Montag bereitstellen. Wir können darüber sprechen, warum eine solche Situation aufgetreten ist, die Sie jetzt am Freitag bereitstellen möchten. “ Es mag zum ersten Mal schmerzhaft sein, dem Kunden oder den Managern dies zu sagen, aber später gewöhnen sich die Leute daran, lernen und bitten Sie nicht, am Freitagabend etwas sehr Dringendes zu tun. Sie verstehen, dass erstens am vergangenen Freitag niemand gestorben ist, als niemand überflutet wurde und sogar niemand Geld verloren hat. Ich versuche nichts zu tun, was mir schaden könnte.

Die gleiche Geschichte über Fehler - wenn es viele Fehler gibt, die ständig behoben werden müssen, lautet die Frage: Warum treten diese Fehler auf? Wir sollten sie nicht reparieren, sondern darüber nachdenken, warum es so viele von ihnen gibt, woher sie kommen, und hauptsächlich mit dem Grundproblem kämpfen. Dies sind auch immer schmerzhafte Probleme, wenn ein Manager oder Kunde sagt, dass eine Funktion in der Produktion dringend behoben werden muss. Aber Sie müssen in der Lage sein zu sagen, dass wenn ich diesen Code jetzt berühre, Sie vielleicht etwas anderes als diese Funktion haben und keine Produktion haben, da der Code nicht durch Tests abgedeckt ist, können Sie keinen weiteren hinzufügen, wenn, weil Wir können uns nicht erinnern, was die anderen sechs tun.

Manchmal müssen Sie sich selbst überwinden und anfangen zu reden. Dies ist nicht immer möglich. Es ist notwendig, bis zu einem gewissen Grad zu erkennen, dass Sie dafür verantwortlich sind, wie viel Zeit Sie für welche Art von Arbeit aufwenden.

Deshalb habe ich wahrscheinlich Zeit. Weil ich versuche, meine Arbeitszeit zu optimieren, damit es eine bestimmte Anzahl von Stunden dauert, bis eine Aufgabe erledigt ist. Gleichzeitig verstehe ich, dass in einer guten Struktur 1-2 Stunden für technische Schulden und einige Verbesserungen zur Verfügung stehen sollten.

Ich werde nicht sagen, dass ich 8 Stunden arbeite, ohne aufzustehen. Ich würde mir einen Entwickler ansehen, der 8 Stunden lang Code sitzt und schreibt. Wenn Sie meinen üblichen Arbeitstag nehmen, dann sind 2 Stunden nur alle Arten von Tests, Codeüberprüfung, technische Schulden, "Buzz" auf dem Code. Stunden 3 ist eine Lösung für aktuelle Probleme, eine Stunde für die Kommunikation mit Managern. Und die restlichen 2 Stunden sind aus irgendeinem Grund verteilt, um mit Teams und freiberuflichen Mitarbeitern zu diskutieren.

Es gibt Dinge, an denen Sie interessiert sind - Sie tun es, und wenn Sie keine Kraft haben, geben sie Ihnen Kraft. Ich habe viele verschiedene Aktivitäten - dies wird wahrscheinlich als nützlicher Aufschub bezeichnet -, wenn ich das tue, woran ich gerade interessiert bin, und nicht das, was ich tun muss. Wenn Sie lernen, zwischen dem Interessanten und dem, was noch benötigt wird, zu variieren, erweist es sich als das erfolgreichste. Sie verschwenden keine Zeit damit, das zu tun, was Sie nicht wollen.

Es gibt kein Geheimnis, Sie müssen nur tun, was Sie wollen, aber gleichzeitig ohne Schaden für Ihre Umgebung und das Projekt.

Einzelheiten zur Implementierung der Testgenerierung aus Python-Code sowie zur Lösung vieler anderer Aufgaben eines Python-Entwicklers finden Sie in Moscow Python Conf ++ , das wir auf den 15. September verschoben haben.

All Articles