Ve své práci aktivně využíváme platformu SonarQube pro udržení kvality kódu na vysoké úrovni. Při integraci jednoho z projektů napsaného na VueJs+Typescript, vznikly problémy. Proto bych chtěl podrobněji popsat, jak se nám je podařilo vyřešit.

V tomto článku se, jak jsem již zmínil, budeme zabývat platformou SonarQube. Stručně teorie – co to vlastně je, pro ty, kteří o ní slyší poprvé:
SonarQube (dříve Sonar) – platforma s otevřeným zdrojovým kódem pro kontinuální analýzu a měření kvality kódu.
Podporuje analýzu kódu a hledání chyb podle pravidel standardů programování MISRA C, MISRA C++, MITRE/CWE a CERT Secure Coding Standards. Umí také rozpoznávat chyby z seznamů OWASP Top-10 a CWE/SANS Top-25 chyb programování.
Ačkoli platforma používá různé hotové nástroje, SonarQube shrnuje výsledky do jediné informační panelu (dashboard), sleduje historii běhů a umožňuje tak vidět obecný trend změny kvality softwaru během vývoje.
Podrobnější informace naleznete na
Podporuje širokou škálu programovacích jazyků. Podle informací z výše uvedeného odkazu – je to více než 25 jazyků. Pro podporu konkrétního jazyka je nutné nainstalovat odpovídající plugin. V community verzi je zahrnut plugin pro práci s Javascript (včetně typescript), ačkoli v wiki je napsáno opak. Za Javascript odpovídá plugin SonarJS, za Typescript SonarTS odpovídajícím způsobem.
Pro odesílání informací o pokrytí se používá oficiální klient sonarqube-scanner, který, používající nastavení z config-souboru, odesílá tato data na server SonarQube pro další konsolidaci a agregaci.
Pro Javascript položka „Přesunout karty“. Kromě toho . Takže začneme krok za krokem zavádět SonarQube v Vue-projekt, který používá Typescript.
Pro nasazení serveru SonarQube využijeme docker-compose.
sonar.yaml:
version: '1'
services:
simplesample-sonar:
image: sonarqube:lts
ports:
- 9001:9000
- 9092:9092
network_mode: bridgeSpuštění:
docker-compose -f sonar.yml upPo tomto SonarQube bude dostupný na adrese – .

V tuto chvíli v něm nejsou projekty, a to je pravda. Budeme tuto situaci řešit. Základem jsem vzal oficiální projektový příklad pro VueJS+TS+Jest. Klonujeme ho k sobě:
git clone https://github.com/vuejs/vue-test-utils-typescript-example.gitNejprve potřebujeme nainstalovat klienta SonarQube, který se nazývá sonar-scanner, pro npm je obal:
yarn add sonarqube-scannerA hned přidáme příkaz do scripts pro práci s ním.
package.json:
{
…
scripts: {
...
"sonar": "sonar-scanner"
...
},
…
}Dále, pro fungování skeneru je potřeba nastavit projektové parametry ve speciálním souboru. Začněme se základními.
sonar-project.properties:
sonar.host.url=http://localhost:9001
sonar.projectKey=test-project-vuejs-ts
sonar.projectName=Test Application (VueJS+TS)
sonar.sources=src
# sonar.tests=
sonar.test.inclusions=src/**/*tests*/**
sonar.sourceEncoding=UTF-8- sonar.host.url – adresa Sonar’a;
- sonar.projectKey – jedinečný identifikátor projektu na serveru Sonar’a;
- sonar.projectName – jeho název, může být změněn kdykoliv, protože identifikace projektu probíhá na základě projectKey;
- sonar.sources – složka se zdrojovými kódy, obvykle je to src, ale může být jakákoli. Tato složka je určena vzhledem ke kořenové složce, kterou je složka, ze které je skener spuštěn;
- sonar.tests – parametr, který jde v páru s předchozím. To je složka, kde se nacházejí testy. V tomto projektu není taková složka, a test se nachází vedle testované komponenty ve složce ‘test‘, proto jej prozatím ignorujeme a využijeme další parametr;
- sonar.test.inclusions – cesta pro testy s použitím vzoru, může být několik prvků uvedených čárkou;
- sonar.sourceEncoding – kódování pro zdrojové soubory.
Pro první spuštění skeneru je vše připraveno, kromě hlavního předchozího kroku: spuštění samotného testovacího motoru pro vytvoření informací o pokrytí, které následně skener použije.
Ale pro to je potřeba nastavit testovací motor na generování těchto informací. V tomto projektu je testovací motor — Jest. A jeho nastavení se nachází v odpovídající části souboru package.json.
Přidáme tato nastavení:
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*",
"!src/main.ts",
"!src/App.vue",
"!src/**/*d.*",
"!src/**/*__tests__*"
],To znamená, že nastavujeme samotnou vlajku nutnosti výpočtu pokrytí a zdroj (spolu s výjimkami), na základě kterých bude pokrytí vytvořeno.
Nyní spusťme test:
yarn testUvidíme následující:

Důvodem je, že v samotné komponentě, jak takové, žádný kód není. Opravy provedeme.
HelloWorld.vue:
...
methods: {
calc(n) {
return n + 1;
}
},
mounted() {
this.msg1 = this.msg + this.calc(1);
},
...To bude stačit pro výpočet pokrytí.
Po restartování testu se o tom ujistíme:

Na obrazovce bychom měli vidět informace o pokrytí, a ve složce projektu bude vytvořena složka coverage s informacemi o pokrytí testy ve univerzálním formátu LCOV (rozšíření LTP GCOV).
Gcov — volně distribuovaný nástroj pro analýzu pokrytí kódu. Gcov generuje přesný počet provedení pro každý příkaz v programu a umožňuje přidat anotace ke zdrojovému kódu. Gcov je dodáván jako standardní nástroj v rámci balíčku GCC.
Lcov — grafické rozhraní pro gcov. Shromažďuje gcov soubory pro více souborů se zdrojovým kódem a vytváří sadu HTML stránek se kódem a informacemi o pokrytí. Rovněž se generují stránky pro usnadnění navigace. Lcov podporuje pokrytí řádků, funkcí a větvení.
Po provedení testů budou informace o pokrytí dostupné v coverage/lcov.info.
Musíme říct Sonarodkud je vzít. Proto přidáme následující řádky do jeho konfiguračního souboru. Ale je tu jeden háček: projekty mohou být vícejazyčné, tedy v adresáři src se nacházejí zdrojové kódy pro několik programovacích jazyků a jejich příslušnost k tomu či onomu, a nakonec použití toho či onoho pluginu, se určuje podle jeho přípony. A informace o pokrytí mohou být uloženy na různých místech pro různé programovací jazyky, proto pro každý programovací jazyk existuje vlastní sekce pro nastavení. Náš projekt používá Typescript, proto potřebujeme sekci nastavení právě pro něj:
sonar-project.properties:
sonar.typescript.coveragePlugin=lcov
sonar.typescript.lcov.reportPaths=coverage/lcov.infoVšechno je připraveno na první spuštění skenery. Chci podotknout, že projekt v Sonarse automaticky vytváří při prvním spuštění skenery pro tento projekt. Při následných spuštěních se již informace budou hromadit, abychom viděli dynamiku změn parametrů projektu v čase.
Takže použijeme příkaz, který byl vytvořen dříve v package.json:
yarn run sonar Poznámka: můžeme také využít parametr -X pro podrobnější logování.
Pokud byl skener spuštěn poprvé, nejprve se stáhne binární soubor samotného skeneru. Poté se spustí a začne skenovat server Sonarna přítomnost nainstalovaných pluginů, čímž se vypočítají podporované programovací jazyky. Také se stahují další různé parametry pro jeho provoz: quality profiles, active rules, metrics repository, server rules.


Poznámka: podrobně na nich se nebudeme zastavovat v rámci tohoto článku, ale vždy se můžete obrátit na oficiální zdroje.
Následuje analýza složky src o přítomnosti zdrojových souborů pro všechny (pokud není výslovně uveden nějaký konkrétní) podporované programovací jazyky, s následnou jejich indexací.

Následují další různé analýzy, na které se v tomto článku nezaměřujeme (například: linting, určování duplicitního kódu atd.).
Na konci práce skeneru dochází k agregaci všech shromážděných informací, archivaci a jejich odeslání na server.
Po tomto už se můžeme podívat, co vzniklo ve webovém rozhraní:

Jak vidíme, něco vzniklo a dokonce to ukazuje určité pokrytí, ale to neodpovídá našemu Jest-reportu.
Pojďme se podívat blíže. Prozkoumávejme projekt podrobněji, klikněme na hodnotu pokrytí a "přejdeme" do podrobného reportu podle souborů:

Zde vidíme kromě hlavního zkoumaného souboru HelloWorld.vue, je zde i soubor main.ts, který kazí celkový obrázek pokrytí. Jak je to možné, když byl vyloučen z výpočtu pokrytí? Ano, je to pravda, ale bylo to na úrovni Jest, ale skener ho proindexoval, a tak se dostal do jeho výpočtů.
Pojďme to opravit:
sonar-project.properties:
...
sonar.exclusions=src/main.ts
...Chci upřesnit: kromě složek, které jsou uvedeny v tomto parametru, se také přidávají všechny složky vyjmenované v parametru sonar.test.inclusions.
Po spuštění skeneru vidíme už správné informace:


Rozveďme další bod – Quality profiles. Již jsem zmínil podporu Sonarpro několik programovacích jazyků zároveň. To právě pozorujeme. Ale víme, že projekt máme napsaný v TS, tak proč zatěžovat skener zbytečnými manipulacemi a kontrolami. Jazyk pro analýzu nastavíme přidáním dalšího parametru do konfiguračního souboru Sonar‘a:
sonar-project.properties:
...
sonar.language=ts
...Znovu spustíme skener a podíváme se na výsledek:

Pokrytí zcela zmizelo.
Pokud se podíváme do logu skeneru, můžeme vidět následující řádek:
![]()
To znamená, že soubory našeho projektu nebyly prostě proindexovány.
Situace je následující: oficiálně je podpora VueJs v pluginu, který odpovídá za SonarJS. Ale tato podpora není v pluginu Javascript.

, o čemž je založen oficiální tiket v bug-trackeru. SonarTS pro TSZde jsou některé odpovědi jednoho z představitelů ze strany vývojářů SonarQube, potvrzující tento fakt. Sonar‘a:
Vy ale můžete namítnout, že všechno fungovalo. Ano, to je pravda, zkuste trochu “hackovat”


Pokud je podpora .vue.
-souborů .-souborů Sonartakže zkusme mu říct, aby je zvažoval jako Typescript.
Přidáme parametr:
sonar-project.properties:
...
sonar.typescript.file.suffixes=.ts,.tsx,.vue
...Spustíme skener:

A je to, všechno se vrátilo do starých kolejí s jedním profilem pouze pro Typescript. To znamená, že se podařilo vyřešit problém s podporou VueJs+TS pro SonarQube.
Zkusíme jít dál a trochu vylepšit informace o pokrytí.
Co jsme dosud udělali:
- přidali jsme do projektu Sonar-skener;
- nastavili jsme Jest pro generování informací o pokrytí;
- konfigurovali jsme Sonar-skener;
- vyřešili problém s podporou .-souborů + Typescript.
Kromě pokrytí testy existují i další zajímavé a užitečné kritéria kvality kódu, například duplicita kódu a počet řádků (podílí se na výpočtu koeficientů souvisejících se složitostí kódu) projektu.
V současné implementaci pluginu pro práci s TS (SonarTS) nebude fungovat CPD (Copy Paste Detector) a počítání řádků kódu .-souborů.
Abychom vytvořili umělou situaci pro duplicitu kódu, jednoduše zduplikujeme soubor komponentu s jiným názvem, také přidáme do kódu main.ts prázdnou funkci a zduplikujeme ji s jiným názvem. Abychom zkontrolovali duplicitu jako v ., tak i v .ts -souborech.
main.ts:
...
funkce jméno(parametry:string): void {
console.log(parametry);
}
...K tomu je potřeba dočasně zakomentovat řádek konfigurace:
sonar-project.properties:
...
sonar.exclusions=src/main.ts
...Znovu spustíme skener společně s testováním:
yarn test && yarn run sonarSamozřejmě, že pokrytí poklesne, ale teď nás to nezajímá.
Z pohledu duplicity řádků kódu uvidíme:

Pro kontrolu využijeme CPD-nástroj – jscpd:
npx jscpd src
Pro řádky kódu:

Možná, že to bude vyřešeno v budoucích verzích pluginů SonarJS(TS). Chci poznamenat, že je postupně začínají slučovat do jednoho SonarJS, což považuji za správné.
Teď bych chtěl zvážit možnost vylepšení informací o pokrytí.
Zatím vidíme pokrytí testy v procentuálním vyjádření v celém projektu, a podle souborů zvlášť. Ale je možné rozšířit tento ukazatel informacemi o počtu unit-testů v projektu, stejně jako podle souborů.
Existuje knihovna, která umí Jest-report převést do formátu pro Sonar‘a:
generic test data — .
Nainstalujeme tuto knihovnu do našeho projektu:
yarn add jest-sonar-reporterA přidáme ji do konfigurace Jest:
package.json:
…
"testResultsProcessor": "jest-sonar-reporter"
…Nyní provedeme test:
yarn testPo čemž bude v kořenovém adresáři projektu vytvořen soubor test-report.xml.
Začleníme ho do konfigurace Sonar‘a:
sonar-project.properties:
…
sonar.testExecutionReportPaths=test-report.xml
…A znovu spustíme skener:
yarn run sonarPodíváme se, co se změnilo v rozhraní Sonar‘a:

A nic se nezměnilo. Je to tím, že Sonar nepovažuje soubory popsané ve zprávě Jest za soubory unit-testů. Abychom tuto situaci napravili, použijeme konfiguraci Sonar sonar.tests, ve které jasně uvedeme složky s testy (zatím máme jen jednu):
sonar-project.properties:
…
sonar.tests=src/components/__tests__
…Restartujeme skener:
yarn run sonarPodíváme se, co se změnilo v rozhraní:

Nyní jsme viděli počet našich unit-testů a při kliknutí dovnitř můžeme vidět rozdělení tohoto čísla podle souborů projektu:

Závěr
Takže jsme se podívali na nástroj pro nepřetržitou analýzu SonarQube. Úspěšně jsme do něj integrovali projekt napsaný v VueJs+TS. Vyřešili jsme některé problémy s kompatibilitou. Zlepšili jsme informativnost ukazatele pokrytí testy. V tomto článku jsme se podívali pouze na jeden z kriterií kvality kódu (možná jeden z hlavních), ale SonarQube podporuje i další kritéria kvality, včetně testování na bezpečnost. Ale ne všechny tyto možnosti jsou v plné míře dostupné v community-verzi. Jednou z zajímavých a užitečných funkcí jsou integrace SonarQube s různými systémy správy kódu, například jako GitLab a BitBucket. Aby se zabránilo merge pull (merge) requestudo hlavní větve repozitáře při degradaci pokrytí. Ale to už je příběh zcela jiného článku.
PS: Vše, co je v článku popsáno jako kód, je dostupné v .
Pouze registrovaní uživatelé se mohou účastnit ankety. , prosím.
Používáte platformu SonarQube:
26,3%Ano5
15,8%Ne3
15,8%Slyšel jsem o této platformě a chci ji použít3
10,5%Slyšel jsem o této platformě a nechci ji použít2
0,0%Používám jinou platformu0
31,6%Poprvé o ní slyším6
Hlasovalo 19 uživatelů. Zdrželi se 3 uživatelé.
Zdroj: habr.com
