Verbessern eines persönlichen Programmierprozesses mit Sensei
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.*"
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
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.
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 buchenAlan 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.
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.*"
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
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.*"
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
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 buchenAlan 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.
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.*"
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
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 buchenHerunterladenRessourcen für den Einstieg
Benchmarking von Sicherheitskompetenzen: Optimierung von Secure-by-Design im Unternehmen
Die Secure-by-Design-Bewegung ist die Zukunft der sicheren Softwareentwicklung. Erfahren Sie mehr über die wichtigsten Elemente, die Unternehmen berücksichtigen müssen, wenn sie über eine Secure-by-Design-Initiative nachdenken.
DigitalOcean verringert Sicherheitsverschuldung mit Secure Code Warrior
DigitalOceans Einsatz von Secure Code Warrior hat die Sicherheitsverschuldung deutlich reduziert, so dass sich die Teams stärker auf Innovation und Produktivität konzentrieren können. Die verbesserte Sicherheit hat die Produktqualität und den Wettbewerbsvorteil des Unternehmens gestärkt. Mit Blick auf die Zukunft wird der SCW Trust Score dem Unternehmen helfen, seine Sicherheitspraktiken weiter zu verbessern und Innovationen voranzutreiben.
Ressourcen für den Einstieg
Trust Score zeigt den Wert von Secure-by-Design-Upskilling-Initiativen
Unsere Forschung hat gezeigt, dass Schulungen für sicheren Code funktionieren. Trust Score verwendet einen Algorithmus, der auf mehr als 20 Millionen Lerndaten aus der Arbeit von mehr als 250.000 Lernenden in über 600 Organisationen basiert, und zeigt, wie effektiv die Initiative ist, um Schwachstellen zu beseitigen und wie man sie noch effektiver gestalten kann.
Reaktive versus präventive Sicherheit: Prävention ist das bessere Heilmittel
Der Gedanke, Legacy-Code und -Systeme zur gleichen Zeit wie neuere Anwendungen mit präventiver Sicherheit auszustatten, kann entmutigend erscheinen, aber ein Secure-by-Design-Ansatz, der durch die Weiterbildung von Entwicklern durchgesetzt wird, kann die besten Sicherheitsverfahren auf diese Systeme anwenden. Dies ist für viele Unternehmen die beste Chance, ihre Sicherheitslage zu verbessern.
Die Vorteile eines Benchmarking der Sicherheitskompetenzen von Entwicklern
Der zunehmende Fokus auf sicheren Code und Secure-by-Design-Prinzipien erfordert, dass Entwickler von Beginn des SDLC an in Cybersicherheit geschult werden, wobei Tools wie Secure Code Warrior's Trust Score dabei helfen, ihre Fortschritte zu messen und zu verbessern.
Wesentlicher Erfolg für Enterprise Secure-by-Design-Initiativen
Unser jüngstes Forschungspapier „Benchmarking Security Skills: Streamlining Secure-by-Design in the Enterprise“ ist das Ergebnis einer umfassenden Analyse echter Secure-by-Design-Initiativen auf Unternehmensebene und der Ableitung von Best-Practice-Ansätzen auf Grundlage datengesteuerter Erkenntnisse.