Blog

Verbessern eines persönlichen Programmierprozesses mit Sensei

Alan Richardson
Veröffentlicht Dez 07, 2020

In diesem Beitrag habe ich einen "schlechten" Kodierungsansatz nachgebildet, den ich verwendet habe, als ich JUnit lernte, und werde demonstrieren, wie man das "schlechte" Muster in ein vereinbartes und "besseres" Kodierungsmuster mit Sensei umwandelt.

Als ich JUnit lernte, konnte ich immer nur so viel in meinem Kopf behalten. Ich vergaß ständig, wie man Tests überspringt, wenn sie nicht funktionierten.

Wenn wir in einem Team arbeiten, können wir Code-Reviews auf Pull-Requests verwenden, um Codierungsstile durchzusetzen. Und wir können den Feedback-Zyklus bei der Paarprogrammierung mit einem erfahreneren Programmierer verkürzen.

Wir können unseren Prozess auch mit Werkzeugen erweitern und uns von den Werkzeugen auffordern lassen, das Richtige zu tun. Thoughtworks beschrieb dies in ihrer Auflistung im Technology Radar für Sensei als "Tools over rules", um: "es einfach zu machen, das Richtige zu tun, anstatt checklistenartige Governance-Regeln und -Verfahren anzuwenden"


Deaktivieren eines JUnit-Tests


Idealerweise würde ich, wie wir alle wissen, die @Disabled-Anmerkung verwenden und schreiben:

  @Disabled
  @Test
  void canWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
   }

Aber beim Lernen musste ich mir antrainieren, @Disabled zu verwenden.

Wenn ich vergessen habe, wie ich eine Testmethode deaktivieren kann, habe ich die @Test-Annotation entfernt und den Test umbenannt:

class SkipThisTest {
    void SKIPTHIScanWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
    }   
}


Es war nicht gut, aber es hat den Job erledigt. Ich hatte nicht so etwas wie Sensei , um mir zu helfen, mich zu erinnern, und so fiel ich in die Verwendung schlechter Codierungsmuster.

Die Aufgaben, die ich mir für diesen Beitrag vorgenommen habe, sind:

  • Erstellen Sie eine Regel, die Methoden findet, die "übersprungen" oder "deaktiviert" wurden, indem Sie die Methode umbenennen.
  • Erstellen Sie einen QuickFix, um die Methode umzubenennen und fügen Sie sowohl eine @Test- als auch eine @Disabled-Anmerkung hinzu.


Rezeptur-Einstellungen

Der erste Schritt, den ich mit Sensei mache, ist "neues Rezept hinzufügen" und nach dem Codierungsmuster zu suchen, auf das das Rezept wirken soll.

Name: JUnit: @Disabled @Test aus SKIPTHIS machen

Kurzbeschreibung: Hören Sie auf, Methoden SKIPTHIS zu benennen, verwenden Sie stattdessen @Disabled @Test


Und meine Suche ist sehr einfach. Ich verwende eine einfache Regex, um den Methodennamen zu finden.

Suche:
Methode:
Name:
Treffer: "SKIPTHIS.*"


Rezepteinstellungen zum Überspringen eines Tests


QuickFix-Einstellungen

Der QuickFix ist etwas komplizierter, da der Code neu geschrieben wird.

Ich möchte es:

  • Fügen Sie der Methode eine @Test-Annotation hinzu
  • Fügen Sie der Methode eine @Disabled-Anmerkung hinzu
  • Ändern Sie den Methodennamen

Das Hinzufügen der Anmerkungen ist mit dem addAnnotation-Fix einfach genug. Wenn ich einen voll qualifizierten Namen für die Anmerkung verwende, fügt Sensei automatisch die Importe für mich hinzu.

availableFixes:
- name: "Add @Disabled and @Test Annotation"
  actions:
- addAnnotation:
annotation: "@org.junit.jupiter.api.Test"
- addAnnotation:
annotation: "@org.junit.jupiter.api.Disabled"


Das eigentliche Umbenennen scheint etwas komplizierter zu sein, aber ich verwende nur eine Regex-Ersetzung, und der generische Weg, dies mit Sensei zu tun, ist, sed in einer Rewrite-Aktion zu verwenden.

Da es sich bei den Rewrite-Aktionen um Mustache-Vorlagen handelt, verfügt Sensei über einige funktionale Erweiterungen im Vorlagenmechanismus. Eine Funktion wird mit {{#...}} dargestellt, für sed lautet die Funktion also {{#sed}}. Die Funktion nimmt zwei durch Komma getrennte Argumente entgegen.

Das erste Argument ist die sed-Anweisung:

  • s/(.*) SKIPTHIS(.*)/$1 $2/

Das zweite Argument ist die Zeichenkette, auf die die sed-Anweisung angewendet werden soll, was in diesem Fall die Methode selbst ist und in den Mustache-Variablen wie folgt dargestellt wird:

  • {{{.}}}

Geben Sie mir die Umschreibeaktion von:

 - umschreiben:

       to: "{{#sed}}s/(.*) SKIPTHIS(.*)/$1 $2/,{{{.}}}{{/sed}}"



Die sed-Implementierung erfordert, dass, wenn die Argumente selbst Kommas enthalten, diese mit {{#encodeString}} und {{/encodeString}} umschlossen werden - z. B. {{#encodeString}}{{{.}}}{{{/encodeString}}

Umgekehrtes Rezept

Da es sich hier um ein Beispiel handelt und wir dies vielleicht in Demos verwenden wollen, wollte ich untersuchen, wie man die obige Änderung mit einem Sensei Rezept rückgängig machen kann.

Wenn ich darüber nachdenke, möchte ich eine mit @Disabled annotierte Methode finden, aber nur in der Klasse SkipThisTest, in der ich die Demo mache:

Name: JUnit: Demo in SkipThisTest @Disabled entfernen und auf SKIPTHIS umstellen

Kurzbeschreibung: @Disabled entfernen und auf SKIPTHIS für Demozwecke im Projekt zurücksetzen

Pegel: Warnung


Die Suche in den Rezepteinstellungen ist sehr einfach, da sie die Anmerkung in einer bestimmten Klasse findet.

search:
method:
annotation:
type: "Deaktiviert"
in:
Klasse:
Name: "SkipThisTest"


Um zu vermeiden, dass der Code wie ein Fehler aussieht, habe ich die allgemeine Einstellung im Rezept als Warnung definiert. Warnungen werden mit Hervorhebungen im Code angezeigt und lassen den Code nicht so aussehen, als hätte er ein großes Problem.

Für die Schnellbehebung, da wir die Methode angepasst haben, verwende ich die Rewrite-Aktion und fülle die Vorlage mit den Variablen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"


Ich füge alle Variablen außer dem Modifikator hinzu (da ich die Anmerkungen loswerden möchte) und füge den SKIPTHIS-Text in die Vorlage ein.

Diese Lösung hat die Schwäche, dass ich durch das Entfernen der Modifikatoren auch alle anderen Anmerkungen entferne.


Weitere Aktion hinzufügen

Ich kann einen weiteren benannten Fix hinzufügen, um mir eine Auswahl zu geben, wenn die Alt+Eingabe verwendet wird, um den QuickFix anzuzeigen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"
- name: "Remove Disabled, keep other annotations, and rename to SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}\n\
        {{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"


Hier habe ich im neuen Quick Fix eine zusätzliche Zeile eingefügt.

//,{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}


Dies nimmt die Modifier-Liste, kodiert sie als Zeichenkette und verwendet dann sed, um die Zeile mit @Disabled aus der Zeichenkette zu entfernen, lässt aber alle anderen Zeilen im Modifier, d. h. es lässt alle anderen Anmerkungen in Ruhe.

HINWEIS: Vergessen Sie nicht, das "," im sed hinzuzufügen, sonst wird ein Kommentar zu Ihrer Vorschau hinzugefügt. Auf diese Weise macht Sensei Sie auf Syntaxfehler im sed-Befehl aufmerksam.

/* e.g: {{#sed}}s/all/world/,helloall{{/sed}} */


Verschachtelte sed-Aufrufe

Ich hatte das Glück, dass ich sowohl @Disabled als auch @Test in einer einzigen Suche und Ersetzung zuordnen konnte.

Wenn der Code komplizierter ist und ich eine Folge von sed-Befehlen haben möchte, kann ich das durch Verschachtelung erreichen:

{{#sed}}s/@Test//,{{#sed}}s/@Disabled\n//,{{{ modifierList }}}{{/sed}}{{/sed}}


Im obigen Beispiel wende ich die @Test-Ersetzung auf die Ergebnisse der Anwendung der @Disabled-Ersetzung auf die {{{ modifierList }}} an.


Zusammenfassung

sed ist ein sehr flexibler Weg, um das Umschreiben von Code zu erreichen, und es ist möglich, die sed-Funktionsaufrufe für komplizierte Umschreibbedingungen zu verschachteln.

Solche Rezepte sind oft nur vorübergehend, weil wir sie verwenden, um unseren Programmierprozess zu verbessern, und sobald wir das Muskelgedächtnis aufgebaut haben und das schlechte Programmiermuster nicht mehr verwenden, können wir sie im Kochbuch entfernen oder deaktivieren.


---

Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Der gesamte Code für diesen Blog-Beitrag ist auf GitHub im Modul `junitexamples` unseres Blog-Beispiele-Repositorys zu finden https://github.com/SecureCodeWarrior/sensei-blog-examples

Ressource anzeigen
Ressource anzeigen

Lernen Sie, wie Sie Code-Reviews auf Pull-Requests verwenden, um Codierungsstile durchzusetzen. Und verkürzen Sie den Feedback-Zyklus bei der Paarprogrammierung mit einem erfahreneren Programmierer.

Interessiert an mehr?

Alan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.

Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.

Demo buchen
Weitergeben:
Autor
Alan Richardson
Veröffentlicht Dez 07, 2020

Alan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.

Weitergeben:

In diesem Beitrag habe ich einen "schlechten" Kodierungsansatz nachgebildet, den ich verwendet habe, als ich JUnit lernte, und werde demonstrieren, wie man das "schlechte" Muster in ein vereinbartes und "besseres" Kodierungsmuster mit Sensei umwandelt.

Als ich JUnit lernte, konnte ich immer nur so viel in meinem Kopf behalten. Ich vergaß ständig, wie man Tests überspringt, wenn sie nicht funktionierten.

Wenn wir in einem Team arbeiten, können wir Code-Reviews auf Pull-Requests verwenden, um Codierungsstile durchzusetzen. Und wir können den Feedback-Zyklus bei der Paarprogrammierung mit einem erfahreneren Programmierer verkürzen.

Wir können unseren Prozess auch mit Werkzeugen erweitern und uns von den Werkzeugen auffordern lassen, das Richtige zu tun. Thoughtworks beschrieb dies in ihrer Auflistung im Technology Radar für Sensei als "Tools over rules", um: "es einfach zu machen, das Richtige zu tun, anstatt checklistenartige Governance-Regeln und -Verfahren anzuwenden"


Deaktivieren eines JUnit-Tests


Idealerweise würde ich, wie wir alle wissen, die @Disabled-Anmerkung verwenden und schreiben:

  @Disabled
  @Test
  void canWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
   }

Aber beim Lernen musste ich mir antrainieren, @Disabled zu verwenden.

Wenn ich vergessen habe, wie ich eine Testmethode deaktivieren kann, habe ich die @Test-Annotation entfernt und den Test umbenannt:

class SkipThisTest {
    void SKIPTHIScanWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
    }   
}


Es war nicht gut, aber es hat den Job erledigt. Ich hatte nicht so etwas wie Sensei , um mir zu helfen, mich zu erinnern, und so fiel ich in die Verwendung schlechter Codierungsmuster.

Die Aufgaben, die ich mir für diesen Beitrag vorgenommen habe, sind:

  • Erstellen Sie eine Regel, die Methoden findet, die "übersprungen" oder "deaktiviert" wurden, indem Sie die Methode umbenennen.
  • Erstellen Sie einen QuickFix, um die Methode umzubenennen und fügen Sie sowohl eine @Test- als auch eine @Disabled-Anmerkung hinzu.


Rezeptur-Einstellungen

Der erste Schritt, den ich mit Sensei mache, ist "neues Rezept hinzufügen" und nach dem Codierungsmuster zu suchen, auf das das Rezept wirken soll.

Name: JUnit: @Disabled @Test aus SKIPTHIS machen

Kurzbeschreibung: Hören Sie auf, Methoden SKIPTHIS zu benennen, verwenden Sie stattdessen @Disabled @Test


Und meine Suche ist sehr einfach. Ich verwende eine einfache Regex, um den Methodennamen zu finden.

Suche:
Methode:
Name:
Treffer: "SKIPTHIS.*"


Rezepteinstellungen zum Überspringen eines Tests


QuickFix-Einstellungen

Der QuickFix ist etwas komplizierter, da der Code neu geschrieben wird.

Ich möchte es:

  • Fügen Sie der Methode eine @Test-Annotation hinzu
  • Fügen Sie der Methode eine @Disabled-Anmerkung hinzu
  • Ändern Sie den Methodennamen

Das Hinzufügen der Anmerkungen ist mit dem addAnnotation-Fix einfach genug. Wenn ich einen voll qualifizierten Namen für die Anmerkung verwende, fügt Sensei automatisch die Importe für mich hinzu.

availableFixes:
- name: "Add @Disabled and @Test Annotation"
  actions:
- addAnnotation:
annotation: "@org.junit.jupiter.api.Test"
- addAnnotation:
annotation: "@org.junit.jupiter.api.Disabled"


Das eigentliche Umbenennen scheint etwas komplizierter zu sein, aber ich verwende nur eine Regex-Ersetzung, und der generische Weg, dies mit Sensei zu tun, ist, sed in einer Rewrite-Aktion zu verwenden.

Da es sich bei den Rewrite-Aktionen um Mustache-Vorlagen handelt, verfügt Sensei über einige funktionale Erweiterungen im Vorlagenmechanismus. Eine Funktion wird mit {{#...}} dargestellt, für sed lautet die Funktion also {{#sed}}. Die Funktion nimmt zwei durch Komma getrennte Argumente entgegen.

Das erste Argument ist die sed-Anweisung:

  • s/(.*) SKIPTHIS(.*)/$1 $2/

Das zweite Argument ist die Zeichenkette, auf die die sed-Anweisung angewendet werden soll, was in diesem Fall die Methode selbst ist und in den Mustache-Variablen wie folgt dargestellt wird:

  • {{{.}}}

Geben Sie mir die Umschreibeaktion von:

 - umschreiben:

       to: "{{#sed}}s/(.*) SKIPTHIS(.*)/$1 $2/,{{{.}}}{{/sed}}"



Die sed-Implementierung erfordert, dass, wenn die Argumente selbst Kommas enthalten, diese mit {{#encodeString}} und {{/encodeString}} umschlossen werden - z. B. {{#encodeString}}{{{.}}}{{{/encodeString}}

Umgekehrtes Rezept

Da es sich hier um ein Beispiel handelt und wir dies vielleicht in Demos verwenden wollen, wollte ich untersuchen, wie man die obige Änderung mit einem Sensei Rezept rückgängig machen kann.

Wenn ich darüber nachdenke, möchte ich eine mit @Disabled annotierte Methode finden, aber nur in der Klasse SkipThisTest, in der ich die Demo mache:

Name: JUnit: Demo in SkipThisTest @Disabled entfernen und auf SKIPTHIS umstellen

Kurzbeschreibung: @Disabled entfernen und auf SKIPTHIS für Demozwecke im Projekt zurücksetzen

Pegel: Warnung


Die Suche in den Rezepteinstellungen ist sehr einfach, da sie die Anmerkung in einer bestimmten Klasse findet.

search:
method:
annotation:
type: "Deaktiviert"
in:
Klasse:
Name: "SkipThisTest"


Um zu vermeiden, dass der Code wie ein Fehler aussieht, habe ich die allgemeine Einstellung im Rezept als Warnung definiert. Warnungen werden mit Hervorhebungen im Code angezeigt und lassen den Code nicht so aussehen, als hätte er ein großes Problem.

Für die Schnellbehebung, da wir die Methode angepasst haben, verwende ich die Rewrite-Aktion und fülle die Vorlage mit den Variablen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"


Ich füge alle Variablen außer dem Modifikator hinzu (da ich die Anmerkungen loswerden möchte) und füge den SKIPTHIS-Text in die Vorlage ein.

Diese Lösung hat die Schwäche, dass ich durch das Entfernen der Modifikatoren auch alle anderen Anmerkungen entferne.


Weitere Aktion hinzufügen

Ich kann einen weiteren benannten Fix hinzufügen, um mir eine Auswahl zu geben, wenn die Alt+Eingabe verwendet wird, um den QuickFix anzuzeigen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"
- name: "Remove Disabled, keep other annotations, and rename to SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}\n\
        {{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"


Hier habe ich im neuen Quick Fix eine zusätzliche Zeile eingefügt.

//,{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}


Dies nimmt die Modifier-Liste, kodiert sie als Zeichenkette und verwendet dann sed, um die Zeile mit @Disabled aus der Zeichenkette zu entfernen, lässt aber alle anderen Zeilen im Modifier, d. h. es lässt alle anderen Anmerkungen in Ruhe.

HINWEIS: Vergessen Sie nicht, das "," im sed hinzuzufügen, sonst wird ein Kommentar zu Ihrer Vorschau hinzugefügt. Auf diese Weise macht Sensei Sie auf Syntaxfehler im sed-Befehl aufmerksam.

/* e.g: {{#sed}}s/all/world/,helloall{{/sed}} */


Verschachtelte sed-Aufrufe

Ich hatte das Glück, dass ich sowohl @Disabled als auch @Test in einer einzigen Suche und Ersetzung zuordnen konnte.

Wenn der Code komplizierter ist und ich eine Folge von sed-Befehlen haben möchte, kann ich das durch Verschachtelung erreichen:

{{#sed}}s/@Test//,{{#sed}}s/@Disabled\n//,{{{ modifierList }}}{{/sed}}{{/sed}}


Im obigen Beispiel wende ich die @Test-Ersetzung auf die Ergebnisse der Anwendung der @Disabled-Ersetzung auf die {{{ modifierList }}} an.


Zusammenfassung

sed ist ein sehr flexibler Weg, um das Umschreiben von Code zu erreichen, und es ist möglich, die sed-Funktionsaufrufe für komplizierte Umschreibbedingungen zu verschachteln.

Solche Rezepte sind oft nur vorübergehend, weil wir sie verwenden, um unseren Programmierprozess zu verbessern, und sobald wir das Muskelgedächtnis aufgebaut haben und das schlechte Programmiermuster nicht mehr verwenden, können wir sie im Kochbuch entfernen oder deaktivieren.


---

Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Der gesamte Code für diesen Blog-Beitrag ist auf GitHub im Modul `junitexamples` unseres Blog-Beispiele-Repositorys zu finden https://github.com/SecureCodeWarrior/sensei-blog-examples

Ressource anzeigen
Ressource anzeigen

Füllen Sie das folgende Formular aus, um den Bericht herunterzuladen

Wir bitten Sie um Ihre Erlaubnis, Ihnen Informationen über unsere Produkte und/oder verwandte Themen der sicheren Codierung zuzusenden. Wir werden Ihre persönlichen Daten immer mit äußerster Sorgfalt behandeln und sie niemals zu Marketingzwecken an andere Unternehmen verkaufen.

Senden
Um das Formular abzuschicken, aktivieren Sie bitte "Analytics"-Cookies. Sie können die Cookies wieder deaktivieren, sobald Sie fertig sind.

In diesem Beitrag habe ich einen "schlechten" Kodierungsansatz nachgebildet, den ich verwendet habe, als ich JUnit lernte, und werde demonstrieren, wie man das "schlechte" Muster in ein vereinbartes und "besseres" Kodierungsmuster mit Sensei umwandelt.

Als ich JUnit lernte, konnte ich immer nur so viel in meinem Kopf behalten. Ich vergaß ständig, wie man Tests überspringt, wenn sie nicht funktionierten.

Wenn wir in einem Team arbeiten, können wir Code-Reviews auf Pull-Requests verwenden, um Codierungsstile durchzusetzen. Und wir können den Feedback-Zyklus bei der Paarprogrammierung mit einem erfahreneren Programmierer verkürzen.

Wir können unseren Prozess auch mit Werkzeugen erweitern und uns von den Werkzeugen auffordern lassen, das Richtige zu tun. Thoughtworks beschrieb dies in ihrer Auflistung im Technology Radar für Sensei als "Tools over rules", um: "es einfach zu machen, das Richtige zu tun, anstatt checklistenartige Governance-Regeln und -Verfahren anzuwenden"


Deaktivieren eines JUnit-Tests


Idealerweise würde ich, wie wir alle wissen, die @Disabled-Anmerkung verwenden und schreiben:

  @Disabled
  @Test
  void canWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
   }

Aber beim Lernen musste ich mir antrainieren, @Disabled zu verwenden.

Wenn ich vergessen habe, wie ich eine Testmethode deaktivieren kann, habe ich die @Test-Annotation entfernt und den Test umbenannt:

class SkipThisTest {
    void SKIPTHIScanWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
    }   
}


Es war nicht gut, aber es hat den Job erledigt. Ich hatte nicht so etwas wie Sensei , um mir zu helfen, mich zu erinnern, und so fiel ich in die Verwendung schlechter Codierungsmuster.

Die Aufgaben, die ich mir für diesen Beitrag vorgenommen habe, sind:

  • Erstellen Sie eine Regel, die Methoden findet, die "übersprungen" oder "deaktiviert" wurden, indem Sie die Methode umbenennen.
  • Erstellen Sie einen QuickFix, um die Methode umzubenennen und fügen Sie sowohl eine @Test- als auch eine @Disabled-Anmerkung hinzu.


Rezeptur-Einstellungen

Der erste Schritt, den ich mit Sensei mache, ist "neues Rezept hinzufügen" und nach dem Codierungsmuster zu suchen, auf das das Rezept wirken soll.

Name: JUnit: @Disabled @Test aus SKIPTHIS machen

Kurzbeschreibung: Hören Sie auf, Methoden SKIPTHIS zu benennen, verwenden Sie stattdessen @Disabled @Test


Und meine Suche ist sehr einfach. Ich verwende eine einfache Regex, um den Methodennamen zu finden.

Suche:
Methode:
Name:
Treffer: "SKIPTHIS.*"


Rezepteinstellungen zum Überspringen eines Tests


QuickFix-Einstellungen

Der QuickFix ist etwas komplizierter, da der Code neu geschrieben wird.

Ich möchte es:

  • Fügen Sie der Methode eine @Test-Annotation hinzu
  • Fügen Sie der Methode eine @Disabled-Anmerkung hinzu
  • Ändern Sie den Methodennamen

Das Hinzufügen der Anmerkungen ist mit dem addAnnotation-Fix einfach genug. Wenn ich einen voll qualifizierten Namen für die Anmerkung verwende, fügt Sensei automatisch die Importe für mich hinzu.

availableFixes:
- name: "Add @Disabled and @Test Annotation"
  actions:
- addAnnotation:
annotation: "@org.junit.jupiter.api.Test"
- addAnnotation:
annotation: "@org.junit.jupiter.api.Disabled"


Das eigentliche Umbenennen scheint etwas komplizierter zu sein, aber ich verwende nur eine Regex-Ersetzung, und der generische Weg, dies mit Sensei zu tun, ist, sed in einer Rewrite-Aktion zu verwenden.

Da es sich bei den Rewrite-Aktionen um Mustache-Vorlagen handelt, verfügt Sensei über einige funktionale Erweiterungen im Vorlagenmechanismus. Eine Funktion wird mit {{#...}} dargestellt, für sed lautet die Funktion also {{#sed}}. Die Funktion nimmt zwei durch Komma getrennte Argumente entgegen.

Das erste Argument ist die sed-Anweisung:

  • s/(.*) SKIPTHIS(.*)/$1 $2/

Das zweite Argument ist die Zeichenkette, auf die die sed-Anweisung angewendet werden soll, was in diesem Fall die Methode selbst ist und in den Mustache-Variablen wie folgt dargestellt wird:

  • {{{.}}}

Geben Sie mir die Umschreibeaktion von:

 - umschreiben:

       to: "{{#sed}}s/(.*) SKIPTHIS(.*)/$1 $2/,{{{.}}}{{/sed}}"



Die sed-Implementierung erfordert, dass, wenn die Argumente selbst Kommas enthalten, diese mit {{#encodeString}} und {{/encodeString}} umschlossen werden - z. B. {{#encodeString}}{{{.}}}{{{/encodeString}}

Umgekehrtes Rezept

Da es sich hier um ein Beispiel handelt und wir dies vielleicht in Demos verwenden wollen, wollte ich untersuchen, wie man die obige Änderung mit einem Sensei Rezept rückgängig machen kann.

Wenn ich darüber nachdenke, möchte ich eine mit @Disabled annotierte Methode finden, aber nur in der Klasse SkipThisTest, in der ich die Demo mache:

Name: JUnit: Demo in SkipThisTest @Disabled entfernen und auf SKIPTHIS umstellen

Kurzbeschreibung: @Disabled entfernen und auf SKIPTHIS für Demozwecke im Projekt zurücksetzen

Pegel: Warnung


Die Suche in den Rezepteinstellungen ist sehr einfach, da sie die Anmerkung in einer bestimmten Klasse findet.

search:
method:
annotation:
type: "Deaktiviert"
in:
Klasse:
Name: "SkipThisTest"


Um zu vermeiden, dass der Code wie ein Fehler aussieht, habe ich die allgemeine Einstellung im Rezept als Warnung definiert. Warnungen werden mit Hervorhebungen im Code angezeigt und lassen den Code nicht so aussehen, als hätte er ein großes Problem.

Für die Schnellbehebung, da wir die Methode angepasst haben, verwende ich die Rewrite-Aktion und fülle die Vorlage mit den Variablen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"


Ich füge alle Variablen außer dem Modifikator hinzu (da ich die Anmerkungen loswerden möchte) und füge den SKIPTHIS-Text in die Vorlage ein.

Diese Lösung hat die Schwäche, dass ich durch das Entfernen der Modifikatoren auch alle anderen Anmerkungen entferne.


Weitere Aktion hinzufügen

Ich kann einen weiteren benannten Fix hinzufügen, um mir eine Auswahl zu geben, wenn die Alt+Eingabe verwendet wird, um den QuickFix anzuzeigen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"
- name: "Remove Disabled, keep other annotations, and rename to SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}\n\
        {{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"


Hier habe ich im neuen Quick Fix eine zusätzliche Zeile eingefügt.

//,{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}


Dies nimmt die Modifier-Liste, kodiert sie als Zeichenkette und verwendet dann sed, um die Zeile mit @Disabled aus der Zeichenkette zu entfernen, lässt aber alle anderen Zeilen im Modifier, d. h. es lässt alle anderen Anmerkungen in Ruhe.

HINWEIS: Vergessen Sie nicht, das "," im sed hinzuzufügen, sonst wird ein Kommentar zu Ihrer Vorschau hinzugefügt. Auf diese Weise macht Sensei Sie auf Syntaxfehler im sed-Befehl aufmerksam.

/* e.g: {{#sed}}s/all/world/,helloall{{/sed}} */


Verschachtelte sed-Aufrufe

Ich hatte das Glück, dass ich sowohl @Disabled als auch @Test in einer einzigen Suche und Ersetzung zuordnen konnte.

Wenn der Code komplizierter ist und ich eine Folge von sed-Befehlen haben möchte, kann ich das durch Verschachtelung erreichen:

{{#sed}}s/@Test//,{{#sed}}s/@Disabled\n//,{{{ modifierList }}}{{/sed}}{{/sed}}


Im obigen Beispiel wende ich die @Test-Ersetzung auf die Ergebnisse der Anwendung der @Disabled-Ersetzung auf die {{{ modifierList }}} an.


Zusammenfassung

sed ist ein sehr flexibler Weg, um das Umschreiben von Code zu erreichen, und es ist möglich, die sed-Funktionsaufrufe für komplizierte Umschreibbedingungen zu verschachteln.

Solche Rezepte sind oft nur vorübergehend, weil wir sie verwenden, um unseren Programmierprozess zu verbessern, und sobald wir das Muskelgedächtnis aufgebaut haben und das schlechte Programmiermuster nicht mehr verwenden, können wir sie im Kochbuch entfernen oder deaktivieren.


---

Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Der gesamte Code für diesen Blog-Beitrag ist auf GitHub im Modul `junitexamples` unseres Blog-Beispiele-Repositorys zu finden https://github.com/SecureCodeWarrior/sensei-blog-examples

Auf Ressource zugreifen

Klicken Sie auf den unten stehenden Link und laden Sie die PDF-Datei dieser Ressource herunter.

Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.

Bericht ansehenDemo buchen
Weitergeben:
Interessiert an mehr?

Weitergeben:
Autor
Alan Richardson
Veröffentlicht Dez 07, 2020

Alan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.

Weitergeben:

In diesem Beitrag habe ich einen "schlechten" Kodierungsansatz nachgebildet, den ich verwendet habe, als ich JUnit lernte, und werde demonstrieren, wie man das "schlechte" Muster in ein vereinbartes und "besseres" Kodierungsmuster mit Sensei umwandelt.

Als ich JUnit lernte, konnte ich immer nur so viel in meinem Kopf behalten. Ich vergaß ständig, wie man Tests überspringt, wenn sie nicht funktionierten.

Wenn wir in einem Team arbeiten, können wir Code-Reviews auf Pull-Requests verwenden, um Codierungsstile durchzusetzen. Und wir können den Feedback-Zyklus bei der Paarprogrammierung mit einem erfahreneren Programmierer verkürzen.

Wir können unseren Prozess auch mit Werkzeugen erweitern und uns von den Werkzeugen auffordern lassen, das Richtige zu tun. Thoughtworks beschrieb dies in ihrer Auflistung im Technology Radar für Sensei als "Tools over rules", um: "es einfach zu machen, das Richtige zu tun, anstatt checklistenartige Governance-Regeln und -Verfahren anzuwenden"


Deaktivieren eines JUnit-Tests


Idealerweise würde ich, wie wir alle wissen, die @Disabled-Anmerkung verwenden und schreiben:

  @Disabled
  @Test
  void canWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
   }

Aber beim Lernen musste ich mir antrainieren, @Disabled zu verwenden.

Wenn ich vergessen habe, wie ich eine Testmethode deaktivieren kann, habe ich die @Test-Annotation entfernt und den Test umbenannt:

class SkipThisTest {
    void SKIPTHIScanWeAddTwoNumbers(){
        Assertions.fail("this test was skipped and should not run");
    }   
}


Es war nicht gut, aber es hat den Job erledigt. Ich hatte nicht so etwas wie Sensei , um mir zu helfen, mich zu erinnern, und so fiel ich in die Verwendung schlechter Codierungsmuster.

Die Aufgaben, die ich mir für diesen Beitrag vorgenommen habe, sind:

  • Erstellen Sie eine Regel, die Methoden findet, die "übersprungen" oder "deaktiviert" wurden, indem Sie die Methode umbenennen.
  • Erstellen Sie einen QuickFix, um die Methode umzubenennen und fügen Sie sowohl eine @Test- als auch eine @Disabled-Anmerkung hinzu.


Rezeptur-Einstellungen

Der erste Schritt, den ich mit Sensei mache, ist "neues Rezept hinzufügen" und nach dem Codierungsmuster zu suchen, auf das das Rezept wirken soll.

Name: JUnit: @Disabled @Test aus SKIPTHIS machen

Kurzbeschreibung: Hören Sie auf, Methoden SKIPTHIS zu benennen, verwenden Sie stattdessen @Disabled @Test


Und meine Suche ist sehr einfach. Ich verwende eine einfache Regex, um den Methodennamen zu finden.

Suche:
Methode:
Name:
Treffer: "SKIPTHIS.*"


Rezepteinstellungen zum Überspringen eines Tests


QuickFix-Einstellungen

Der QuickFix ist etwas komplizierter, da der Code neu geschrieben wird.

Ich möchte es:

  • Fügen Sie der Methode eine @Test-Annotation hinzu
  • Fügen Sie der Methode eine @Disabled-Anmerkung hinzu
  • Ändern Sie den Methodennamen

Das Hinzufügen der Anmerkungen ist mit dem addAnnotation-Fix einfach genug. Wenn ich einen voll qualifizierten Namen für die Anmerkung verwende, fügt Sensei automatisch die Importe für mich hinzu.

availableFixes:
- name: "Add @Disabled and @Test Annotation"
  actions:
- addAnnotation:
annotation: "@org.junit.jupiter.api.Test"
- addAnnotation:
annotation: "@org.junit.jupiter.api.Disabled"


Das eigentliche Umbenennen scheint etwas komplizierter zu sein, aber ich verwende nur eine Regex-Ersetzung, und der generische Weg, dies mit Sensei zu tun, ist, sed in einer Rewrite-Aktion zu verwenden.

Da es sich bei den Rewrite-Aktionen um Mustache-Vorlagen handelt, verfügt Sensei über einige funktionale Erweiterungen im Vorlagenmechanismus. Eine Funktion wird mit {{#...}} dargestellt, für sed lautet die Funktion also {{#sed}}. Die Funktion nimmt zwei durch Komma getrennte Argumente entgegen.

Das erste Argument ist die sed-Anweisung:

  • s/(.*) SKIPTHIS(.*)/$1 $2/

Das zweite Argument ist die Zeichenkette, auf die die sed-Anweisung angewendet werden soll, was in diesem Fall die Methode selbst ist und in den Mustache-Variablen wie folgt dargestellt wird:

  • {{{.}}}

Geben Sie mir die Umschreibeaktion von:

 - umschreiben:

       to: "{{#sed}}s/(.*) SKIPTHIS(.*)/$1 $2/,{{{.}}}{{/sed}}"



Die sed-Implementierung erfordert, dass, wenn die Argumente selbst Kommas enthalten, diese mit {{#encodeString}} und {{/encodeString}} umschlossen werden - z. B. {{#encodeString}}{{{.}}}{{{/encodeString}}

Umgekehrtes Rezept

Da es sich hier um ein Beispiel handelt und wir dies vielleicht in Demos verwenden wollen, wollte ich untersuchen, wie man die obige Änderung mit einem Sensei Rezept rückgängig machen kann.

Wenn ich darüber nachdenke, möchte ich eine mit @Disabled annotierte Methode finden, aber nur in der Klasse SkipThisTest, in der ich die Demo mache:

Name: JUnit: Demo in SkipThisTest @Disabled entfernen und auf SKIPTHIS umstellen

Kurzbeschreibung: @Disabled entfernen und auf SKIPTHIS für Demozwecke im Projekt zurücksetzen

Pegel: Warnung


Die Suche in den Rezepteinstellungen ist sehr einfach, da sie die Anmerkung in einer bestimmten Klasse findet.

search:
method:
annotation:
type: "Deaktiviert"
in:
Klasse:
Name: "SkipThisTest"


Um zu vermeiden, dass der Code wie ein Fehler aussieht, habe ich die allgemeine Einstellung im Rezept als Warnung definiert. Warnungen werden mit Hervorhebungen im Code angezeigt und lassen den Code nicht so aussehen, als hätte er ein großes Problem.

Für die Schnellbehebung, da wir die Methode angepasst haben, verwende ich die Rewrite-Aktion und fülle die Vorlage mit den Variablen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"


Ich füge alle Variablen außer dem Modifikator hinzu (da ich die Anmerkungen loswerden möchte) und füge den SKIPTHIS-Text in die Vorlage ein.

Diese Lösung hat die Schwäche, dass ich durch das Entfernen der Modifikatoren auch alle anderen Anmerkungen entferne.


Weitere Aktion hinzufügen

Ich kann einen weiteren benannten Fix hinzufügen, um mir eine Auswahl zu geben, wenn die Alt+Eingabe verwendet wird, um den QuickFix anzuzeigen.

availableFixes:
- name: "Disabled entfernen und umbenennen in SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"
- name: "Remove Disabled, keep other annotations, and rename to SKIPTHIS..."
  actions:
  - rewrite:
      to: "{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}\n\
        {{{ returnTypeElement }}} SKIPTHIS{{{ nameIdentifier }}}{{{ parameterList\
        \ }}}{{{ body }}}"
      target: "self"


Hier habe ich im neuen Quick Fix eine zusätzliche Zeile eingefügt.

//,{{#sed}}s/(@Disabled\n.*@Test)//,{{{ modifierList }}}{{/sed}}


Dies nimmt die Modifier-Liste, kodiert sie als Zeichenkette und verwendet dann sed, um die Zeile mit @Disabled aus der Zeichenkette zu entfernen, lässt aber alle anderen Zeilen im Modifier, d. h. es lässt alle anderen Anmerkungen in Ruhe.

HINWEIS: Vergessen Sie nicht, das "," im sed hinzuzufügen, sonst wird ein Kommentar zu Ihrer Vorschau hinzugefügt. Auf diese Weise macht Sensei Sie auf Syntaxfehler im sed-Befehl aufmerksam.

/* e.g: {{#sed}}s/all/world/,helloall{{/sed}} */


Verschachtelte sed-Aufrufe

Ich hatte das Glück, dass ich sowohl @Disabled als auch @Test in einer einzigen Suche und Ersetzung zuordnen konnte.

Wenn der Code komplizierter ist und ich eine Folge von sed-Befehlen haben möchte, kann ich das durch Verschachtelung erreichen:

{{#sed}}s/@Test//,{{#sed}}s/@Disabled\n//,{{{ modifierList }}}{{/sed}}{{/sed}}


Im obigen Beispiel wende ich die @Test-Ersetzung auf die Ergebnisse der Anwendung der @Disabled-Ersetzung auf die {{{ modifierList }}} an.


Zusammenfassung

sed ist ein sehr flexibler Weg, um das Umschreiben von Code zu erreichen, und es ist möglich, die sed-Funktionsaufrufe für komplizierte Umschreibbedingungen zu verschachteln.

Solche Rezepte sind oft nur vorübergehend, weil wir sie verwenden, um unseren Programmierprozess zu verbessern, und sobald wir das Muskelgedächtnis aufgebaut haben und das schlechte Programmiermuster nicht mehr verwenden, können wir sie im Kochbuch entfernen oder deaktivieren.


---

Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Der gesamte Code für diesen Blog-Beitrag ist auf GitHub im Modul `junitexamples` unseres Blog-Beispiele-Repositorys zu finden https://github.com/SecureCodeWarrior/sensei-blog-examples

Inhaltsübersicht

Ressource anzeigen
Interessiert an mehr?

Alan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.

Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.

Demo buchenHerunterladen
Weitergeben:
Ressourcendrehscheibe

Ressourcen für den Einstieg

Mehr Beiträge
Ressourcendrehscheibe

Ressourcen für den Einstieg

Mehr Beiträge