In unserer Arbeit setzen wir aktiv die Plattform ein SonarQube um die Codequalität auf einem hohen Niveau zu halten. Bei der Integration eines Projekts, das in VueJs+Typescript, geschrieben wurde, traten Probleme auf. Daher möchte ich näher erläutern, wie wir diese lösen konnten.

In diesem Artikel wird es, wie bereits erwähnt, um die Plattform SonarQube gehen. Ein wenig Theorie – was ist das überhaupt, für diejenigen, die zum ersten Mal davon hören:
SonarQube (ehemals Sonar) — eine Open-Source-Plattform für kontinuierliche Analyse und Messung der Codequalität.
Sie unterstützt die Analyse von Code und die Fehlersuche gemäß den Programmierstandards MISRA C, MISRA C++, MITRE/CWE und CERT Secure Coding Standards. Außerdem kann sie Fehler aus den OWASP Top-10-Listen und den CWE/SANS Top-25 Programmierfehlern erkennen.
Obwohl die Plattform verschiedene fertige Werkzeuge nutzt, fasst SonarQube die Ergebnisse in einem einheitlichen Dashboard zusammen, führt eine Historie der Durchläufe und ermöglicht es somit, die allgemeinen Trends in der Veränderung der Softwarequalität während der Entwicklung zu sehen.
Weitere Informationen finden Sie auf
Es werden viele Programmiersprachen unterstützt. Laut den Informationen im obigen Link sind es mehr als 25 Sprachen. Um eine bestimmte Sprache zu unterstützen, muss das entsprechende Plugin installiert werden. In der Community-Version ist das Plugin für die Arbeit mit Javascript (einschließlich TypeScript), obwohl im Wiki das Gegenteil steht. Dafür ist das Plugin Javascript SonarJS zuständig, für TypeScriptSonarTS entsprechend. соответственно.
Um Informationen zur Abdeckung zu senden, wird der offizielle Client sonarqube-scannerverwendet, der unter Verwendung der Einstellungen aus der config-Datei diese Daten an den Server sendet SonarQube zur weiteren Konsolidierung und Aggregation.
Für Javascript gibt es Nun beginnen wir mit der schrittweisen Implementierung eines SonarQube in Vue-Projekts, das TypeScript verwendet. Zum Bereitstellen des Servers nutzen wir.
docker-compose. SonarQube sonar.yaml version: '1' services: simplesample-sonar: image: sonarqube:lts ports: - 9001:9000 - 9092:9092 network_mode: bridge.
sonar.yaml:
version: '1'
services:
simplesample-sonar:
image: sonarqube:lts
ports:
- 9001:9000
- 9092:9092
network_mode: bridgeStart:
docker-compose -f sonar.yml upDanach ist es unter der Adresse verfügbar – SonarQube Noch sind keine Projekte darin, und das ist gerechtfertigt. Wir werden diese Situation ändern. Ich habe das offizielle Beispielprojekt für .

VueJS+TS+Jest als Grundlage genommen. Klonen wir es auf unsere Maschine:git clone https://github.com/vuejs/vue-test-utils-typescript-example.git
git clone https://github.com/vuejs/vue-test-utils-typescript-example.gitZuerst müssen wir den Client installieren SonarQube, der heißt sonar-scanner, für npm gibt es eine Wrapper:
yarn add sonarqube-scannerUnd fügen wir sofort den Befehl in scripts zum Arbeiten mit ihm hinzu.
package.json:
{
…
scripts: {
...
"sonar": "sonar-scanner"
...
},
…
}Als Nächstes müssen wir für den Scanner die Projekteinstellungen in einer speziellen Datei festlegen. Beginnen wir mit den Grundlagen.
sonar-project.properties:
sonar.host.url=http://localhost:9001
sonar.projectKey=test-project-vuejs-ts
sonar.projectName=Testanwendung (VueJS+TS)
sonar.sources=src
# sonar.tests=
sonar.test.inclusions=src/**/*tests*/**
sonar.sourceEncoding=UTF-8- sonar.host.url – die Adresse Sonar’s;
- sonar.projectKey – die eindeutige Projekt-ID auf dem Server Sonar’s;
- sonar.projectName – sein Name, der jederzeit geändert werden kann, da die Identifizierung des Projekts über projectKey;
- sonar.sources – der Ordner mit den Quellcodes, in der Regel ist das src, kann aber auch beliebig sein. Dieser Ordner wird relativ zum Root-Ordner festgelegt, von dem aus der Scanner gestartet wurde;
- sonar.tests – ein Parameter, der mit dem vorherigen gekoppelt ist. Dies ist der Ordner, in dem sich die Tests befinden. In diesem Projekt gibt es keinen solchen Ordner, und der Test liegt neben der getesteten Komponente im Ordner ‘test‘, daher ignorieren wir ihn vorerst und verwenden den nächsten Parameter;
- sonar.test.inclusions – Testpfad mit Verwendung einer Maske, es können mehrere Elemente durch Kommas getrennt aufgelistet werden;
- sonar.sourceEncoding – Zeichencodierung für Quellfiles.
Für den ersten Start des Scanners ist alles vorbereitet, außer der grundlegenden vorausgehenden Handlung: dem Start des Testframeworks, um die Abdeckungsinformationen zu generieren, die später vom Scanner verwendet werden.
Dafür muss jedoch das Testframework so konfiguriert werden, dass diese Informationen erstellt werden. In diesem Projekt ist das Testframework Jest. Die Einstellungen dafür befinden sich im entsprechenden Abschnitt der Datei. package.json.
Fügen wir diese Einstellungen hinzu:
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*",
"!src/main.ts",
"!src/App.vue",
"!src/**/*.d.*",
"!src/**/*__tests__*"
],Das heißt, wir aktivieren das Flag für die Notwendigkeit, die Abdeckung zu berechnen, sowie die Quelle (einschließlich der Ausnahmen), auf deren Grundlage sie generiert wird.
Jetzt führen wir den Test aus:
yarn testWir werden Folgendes sehen:

Der Grund dafür ist, dass im Komponent selbst kein Code vorhanden ist. Lass uns das beheben.
HelloWorld.vue:
...
methods: {
calc(n) {
return n + 1;
}
},
mounted() {
this.msg1 = this.msg + this.calc(1);
},
...Das wird ausreichend sein, um die Abdeckung zu berechnen.
Nach dem Neustart des Tests werden wir das überprüfen:

Auf dem Bildschirm sollten wir Informationen zur Abdeckung sehen, und im Projektordner wird ein Ordner erstellt coverage mit Informationen zur Testabdeckung im universellen Format LCOV (LTP GCOV-Erweiterung).
Gcov — ein Open-Source-Tool zur Analyse der Codeabdeckung. Gcov generiert die genaue Anzahl der Ausführungen für jeden Operator im Programm und ermöglicht das Hinzufügen von Anmerkungen zum Quellcode. Gcov wird als Standardtool im GCC-Paket mitgeliefert.
Lcov — eine grafische Benutzeroberfläche für gcov. Es sammelt gcov-Dateien für mehrere Quellcodedateien und erstellt ein Satz von HTML-Seiten mit dem Code und Informationen zur Abdeckung. Zudem werden Seiten zur Vereinfachung der Navigation generiert. Lcov unterstützt die Abdeckung von Zeilen, Funktionen und Verzweigungen.
Nach dem Ausführen der Tests finden Sie die Abdeckungsinformationen in coverage/lcov.info.
Wir müssen ihm sagen Sonarwoher wir sie beziehen. Daher fügen wir die folgenden Zeilen seiner Konfigurationsdatei hinzu. Es gibt jedoch einen Punkt: Projekte können mehrsprachig sein, d.h. im Ordner src Hier finden Sie die Quellcodes für mehrere Programmiersprachen sowie deren Zuordnung. Die Verwendung von Plugins wird durch deren Erweiterung bestimmt. Informationen zur Abdeckung können an verschiedenen Orten für unterschiedliche Programmiersprachen gespeichert werden, weshalb es für jede Programmiersprache einen eigenen Abschnitt zur Konfiguration gibt. Unser Projekt verwendet Zum Bereitstellen des Servers nutzen wir, daher benötigen wir einen speziellen Einstellungsbereich dafür:
sonar-project.properties:
sonar.typescript.coveragePlugin=lcov
sonar.typescript.lcov.reportPaths=coverage/lcov.infoAlles ist bereit für den ersten Start des Scanners. Ich möchte darauf hinweisen, dass das Projekt in Sonarautomatisch beim ersten Start des Scanners für dieses Projekt erstellt wird. Bei weiteren Starts werden die Informationen gesammelt, um die Dynamik der Änderungen der Projektparameter im Zeitverlauf zu beobachten.
Lassen Sie uns also den zuvor erstellten Befehl verwenden in package.json:
yarn run sonar Hinweis: der Parameter -X kann ebenfalls für detailliertere Protokollierung verwendet werden.
Wenn der Scanner zum ersten Mal gestartet wird, wird zunächst die Binärdatei des Scanners heruntergeladen. Danach wird er gestartet und beginnt mit dem Scannen des Servers. Sonarüber die installierten Plugins, dabei wird die unterstützte Programmiersprache ermittelt. Zudem werden weitere verschiedene Parameter für den Betrieb geladen: Qualitätsprofile, aktive Regeln, Metriken-Repository, Serverregeln.


Hinweis: auf die wir im Rahmen dieses Artikels nicht näher eingehen werden, aber man kann jederzeit auf offizielle Quellen zurückgreifen.
Daraufhin beginnt die Analyse des Ordners src auf das Vorhandensein von Quelldateien für alle unterstützten Programmiersprachen (sofern nicht ausdrücklich eine spezifische festgelegt wurde), gefolgt von deren Indizierung.

Darauf folgen weitere verschiedene Analysen, auf die wir in diesem Artikel nicht näher eingehen (beispielsweise Linting, Duplikaterkennung usw.).
Am Ende des Scanners erfolgt die Aggregation aller gesammelten Informationen, die Archivierung und der Versand an den Server.
Danach können wir sehen, was im Webinterface herausgekommen ist:

Wie wir sehen, gibt es Ergebnisse, die sogar eine gewisse Abdeckung zeigen, diese stimmt jedoch nicht mit unserem Jest-Bericht überein.
Lassen Sie uns das klären. Schauen wir uns das Projekt genauer an, klicken wir auf den Abdeckungswert und "tauchen" in den detaillierten Bericht zu den Dateien ein:

Hier sehen wir neben der Hauptdatei, die untersucht wird, HelloWorld.vue, auch die Datei main.ts, die das gesamte Abdeckungsbild beeinträchtigt. Aber wie kann das sein, wir hatten sie doch von der Abdeckung ausgeschlossen. Ja, das ist korrekt, aber das war auf der Ebene Jest, jedoch hat der Scanner sie indexiert, weshalb sie in seine Berechnungen eingeflossen ist.
Lassen Sie uns das beheben:
sonar-project.properties:
...
sonar.exclusions=src/main.ts
...Eine Klarstellung: Neben den in diesem Parameter angegebenen Ordnern werden auch alle Ordner hinzugefügt, die im Parameter sonar.test.inclusions.
Nach dem Start des Scanners sehen wir bereits korrekte Informationen:


Betrachten wir den nächsten Punkt – Qualitätsprofile. Ich hatte oben über die Unterstützung Sonarmehrerer Programmiersprachen gleichzeitig gesprochen. Das beobachten wir hier. Aber wir wissen, dass unser Projekt in TSgeschrieben ist, weshalb wir den Scanner nicht mit überflüssigen Manipulationen und Überprüfungen belasten sollten. Die Sprache für die Analyse definieren wir durch das Hinzufügen eines weiteren Parameters zur Konfigurationsdatei: Sonar... sonar.language=ts ...
sonar-project.properties:
Lassen Sie uns den Scanner erneut starten und das Ergebnis ansehen:Die Abdeckung ist völlig verschwunden.

Wenn wir das Log des Scanners betrachten, können wir die folgende Zeile sehen:
Das bedeutet, dass die Dateien unseres Projekts einfach nicht indexiert wurden.
![]()
То есть файлы нашего проекта просто не были проиндексированы.
Die Situation ist die folgende: Offiziell wird Unterstützung VueJs im Plugin bereitgestellt zuständig, für TypeScript, das für Javascript.

diese Unterstützung aber im Plugin fehlt, entsprechend. für TSworüber ein offizielles Ticket im Bug-Tracker eröffnet wurde. Sonar... sonar.language=ts ...
Hier sind einige Antworten eines der Vertreter von SonarQube, die diese Tatsache bestätigen.


Aber bei uns hat alles funktioniert, werden Sie einwenden. Ja, das stimmt, lassen Sie uns versuchen, ein wenig zu ‚hacken‘.
Wenn es Unterstützung für .vue-Dateien gibt, dann lassen Sie uns versuchen, ihm zu sagen, dass er sie als Sonarbetrachten soll. Zum Bereitstellen des Servers nutzen wir.
Wir fügen einen Parameter hinzu:
sonar-project.properties:
...
sonar.typescript.file.suffixes=.ts,.tsx,.vue
...Wir starten den Scanner:

Und voilà, alles ist wieder wie zuvor, mit einem Profil nur für Zum Bereitstellen des Servers nutzen wir. Das heißt, das Problem mit der Unterstützung wurde gelöst VueJs+TS für SonarQube.
Lassen Sie uns weitergehen und die Informationen über die Abdeckung ein wenig verbessern.
Was haben wir bisher gemacht:
- wir haben im Projekt Sonar-den Scanner hinzugefügt;
- wir haben Jest die Informationen über die Abdeckung konfiguriert;
- wir haben Sonar-den Scanner hinzugefügt;
- das Problem mit der Unterstützung .vue-Dateien gelöst + Zum Bereitstellen des Servers nutzen wir.
Neben der Testabdeckung gibt es auch andere interessante nützliche Qualitätskriterien für den Code, wie z.B. Code-Duplikationen und die Anzahl der Zeilen (die bei der Berechnung der mit der Komplexität des Codes verbundenen Koeffizienten berücksichtigt werden).
In der aktuellen Implementierung des Plugins für die Arbeit mit TS (entsprechend.) wird nicht funktionieren CPD (Copy Paste Detector) und der Zählung von Codezeilen .vue-Dateien.
Um eine synthetische Situation zur Duplizierung von Code zu erstellen, duplizieren wir einfach die Komponenten-Datei unter einem anderen Namen und fügen auch im Code main.ts eine Dummy-Funktion hinzu und duplizieren sie unter einem anderen Namen. Um die Duplizierung zu überprüfen, sowohl in .vueals auch in .ts -Dateien.
main.ts:
...
function name(params:string): void {
console.log(params);
}
...Dazu muss die Zeile in der Konfiguration vorübergehend auskommentiert werden:
sonar-project.properties:
...
sonar.exclusions=src/main.ts
...Starten wir den Scanner und die Tests neu:
yarn test && yarn run sonarUnsere Abdeckung wird natürlich sinken, aber das ist uns jetzt nicht wichtig.
Im Hinblick auf die Duplizierung von Codezeilen sehen wir:

Zur Überprüfung verwenden wir CPD-Tool - jscpd:
npx jscpd src
Für Codezeilen:

Dies könnte in zukünftigen Versionen der Plugins SonarJS(TS) gelöst werden.Ich möchte bemerken, dass sie allmählich beginnen, diese beiden Plugins in eines zu konsolidieren, zuständig, für TypeScriptwas ich für richtig halte.
Jetzt möchte ich eine Verbesserung der Informationen zur Abdeckung betrachten.
Aktuell sehen wir die Testabdeckung prozentual im gesamten Projekt sowie in den einzelnen Dateien. Es gibt jedoch die Möglichkeit, diese Kennzahl um Informationen zur Anzahl unit-Tests im Projekt sowie nach Dateien zu erweitern.
Es gibt eine Bibliothek, die in der Lage ist, Jest-Berichte in ein Format für Sonar... sonar.language=ts ...
generische Testdaten — .
Lass uns diese Bibliothek in unser Projekt installieren:
yarn add jest-sonar-reporterUnd wir fügen sie der Konfiguration hinzu Jest:
package.json:
…
"testResultsProcessor": "jest-sonar-reporter"
…Jetzt führen wir den Test aus:
yarn testNach dem Ausführen wird im Hauptverzeichnis des Projekts eine Datei erstellt test-report.xml.
Wir binden sie in die Konfiguration ein Sonar... sonar.language=ts ...
sonar-project.properties:
…
sonar.testExecutionReportPaths=test-report.xml
…Und starten den Scanner neu:
yarn run sonarLass uns anschauen, was sich in der Benutzeroberfläche geändert hat Sonar... sonar.language=ts ...

Und es hat sich nichts geändert. Der Grund ist, dass Sonar die in dem Jest-Bericht beschriebenen Dateien nicht als Dateien unit-Tests betrachtet. Um diese Situation zu beheben, nutzen wir die Konfigurationsoption Sonar sonar.tests, in der wir die Ordner mit Tests explizit angeben (wir haben bisher nur einen):
sonar-project.properties:
…
sonar.tests=src/components/__tests__
…Wir starten den Scanner erneut:
yarn run sonarLass uns anschauen, was sich in der Benutzeroberfläche geändert hat:

Jetzt haben wir die Anzahl unserer unit-Tests gesehen und können, indem wir darauf klicken, die Verteilung dieser Zahl auf die Projektdateien ansehen:

Fazit
Wir haben also ein Tool für die kontinuierliche Analyse betrachtet SonarQube. Es wurde erfolgreich in ein Projekt integriert, das in VueJs+TS. Einige Kompatibilitätsprobleme wurden gelöst. Die Informationsdichte des Testabdeckungsindikators wurde verbessert. In diesem Artikel haben wir nur ein Kriterium für die Codequalität behandelt (möglicherweise das wichtigste), aber SonarQube es unterstützt auch andere Qualitätskriterien, einschließlich der Sicherheitstests. Allerdings sind nicht alle diese Funktionen in der community-Version vollständig verfügbar. Eine der interessanten und nützlichen Funktionen sind die Integrationen SonarQube mit verschiedenen Systemen zur Verwaltung von Code-Repositories, wie zum Beispiel GitLab und BitBucket. Um zu verhindern, dass ein Merge-Pull-Requestin den Hauptbranch des Repositories bei einer Verschlechterung der Abdeckung gelangt. Aber das ist eine ganz andere Geschichte.
PS: Alles, was im Artikel in Form von Code beschrieben ist, ist in .
Nur registrierte Benutzer können an der Umfrage teilnehmen. Sind Sie an Contour interessiert?
Nutzen Sie die SonarQube-Plattform:
26,3%Ja5
15,8%Nein3
15,8%Habe von dieser Plattform gehört und möchte sie verwenden3
10,5%Habe von dieser Plattform gehört und möchte sie nicht verwenden2
0,0%Nutze eine andere Plattform0
31,6%Höre zum ersten Mal davon6
19 Benutzer haben abgestimmt. 3 Benutzer haben sich enthalten.
Quelle: habr.com
