W dzisiejszych czasach, testowanie oprogramowania jest kluczowym etapem w procesie wytwarzania aplikacji. Dlatego też, w celu zapewnienia jakości kodu, często korzystamy z różnych narzędzi, które pomagają nam w automatyzacji testów i ocenie pokrycia kodu.
Jednym z nich jest SonarQube, czyli aplikacja open source służąca do kontroli jakości kodu, w tym m.in.: do oceny pokrycia kodu, wykrywania błędów czy podatności (OWASP, PCI DSS, CWE – Ryc. 1).
W artykule przyjrzymy się temu, jak można wykorzystać SonarQube do statycznej analizy kodu w aplikacjach C# .NET.
Co to jest statyczna analiza kodu?
Statyczna analiza kodu to proces automatycznego skanowania kodu źródłowego w celu wykrycia:
- błędów,
- potencjalnych zagrożeń bezpieczeństwa,
- niespójności,
- niezgodności z najlepszymi praktykami programistycznymi.
Ważne jest to, że analiza ta przeprowadzana jest zanim kod zostanie uruchomiony.
W przypadku języka C# statyczna analiza kodu może być wykonywana za pomocą różnych narzędzi, w tym specjalistycznych narzędzi IDE (ang. Integrated Development Environment) takich jak Microsoft Visual Studio, jak również zewnętrznych narzędzi, np. SonarQube, ReSharper czy Code Analysis.
Narzędzia te wykorzystują różne techniki i algorytmy do skanowania kodu, uwzględniając reguły statycznej analizy kodu, które pozwalają na wykrywanie potencjalnych błędów. Korzystają również z podejścia opartego na sztucznej inteligencji i uczeniu maszynowym. Umożliwiają identyfikowanie błędów i niespójności na podstawie wcześniejszych wzorców oraz analizy dużych zbiorów danych.
Korzyści płynące ze statycznej analizy kodu
Korzyści wynikające z zastosowania statycznej analizy kodu w języku C# są liczne. Przede wszystkim pozwala ona na wykrycie błędów we wczesnym etapie procesu wytwarzania oprogramowania, co prowadzi do oszczędności czasu i zmniejszenia kosztów poprawek w późniejszych fazach projektu. Po drugie, statyczna analiza kodu pozwala na identyfikowanie potencjalnych zagrożeń bezpieczeństwa, co jest szczególnie istotne w przypadku aplikacji, które wymagają wysokiego poziomu bezpieczeństwa, takich jak aplikacje medyczne, do kierowania ruchem kolejowym lub lotniczym.
Jednym z istotnych elementów analizy statycznej jest pokrycie kodu.
Co to jest pokrycie kodu?
Pokrycie kodu to miara określająca, w jaki sposób testy jednostkowe pokrywają kod źródłowy aplikacji. Im wyższy poziom pokrycia kodu, tym większa pewność, że kod działa zgodnie z oczekiwaniami i jest bardziej odporny na błędy.
Istnieją różne rodzaje pokrycia kodu, takie jak pokrycie instrukcji, gałęzi, wierszy lub funkcji. Każdy z tych rodzajów ma swoje zalety i wady, zaś wybór konkretnego typu zależy od potrzeb projektu.
Co to jest SonarQube?
SonarQube to platforma do ciągłej inspekcji jakości kodu, która zapewnia programistom kompleksowy zestaw narzędzi do analizy i pomiaru jakości ich kodu.
Oferuje szereg funkcji, takich jak:
- analiza kodu,
- pokrycie kodu,
- wykrywanie duplikatów kodu,
- skanowanie pod kątem podatności, aby pomóc programistom w identyfikowaniu i rozwiązywaniu problemów.
SonarQube integruje się z różnymi narzędziami i językami, w tym C#, Java, Python i wieloma innymi, a można go używać zarówno w środowisku lokalnym, jak i w chmurze. Jego przyjazny interfejs i szczegółowe raportowanie sprawiają, że jest łatwy w użyciu i umożliwia szybkie wdrożenie.
W celu przeprowadzenia analizy kodu na naszej maszynie lokalnej, warto przyjrzeć się poszczególnym używanym komponentom i powiązaniom pomiędzy nimi (Ryc. 2):
Dostępne komponenty SonarQube:
- Skaner – proces, który dokonuje analizy kodu źródłowego,
- Baza danych – przechowywane są w niej metryki związane z jakością kodu oraz konfigurację,
- Serwer SonarQube – udostępnia interfejs użytkownika, przetwarza raporty z analizy kodu i zapisuje je do bazy danych.
Instalacja komponentów SonarQube
Server MSSQL
W tym zakresie jest wiele tutoriali, więc opis samej instalacji opuszczę. Istotne jest natomiast, aby spełnić warunki przy tworzeniu bazy danych:
- Collation MUST be case-sensitive (CS) and accent-sensitive (AS) (wersja angielska tego wymagania pozwala na łatwiejsze jego zrozumienie), np. Polish_CS_AS.
- po utworzeniu bazy należy upewnić się, że mamy ustawioną opcję READ_COMMITED_SNAPSHOT:
SELECT is_read_committed_snapshot_on FROM sys.databases WHERE name='TwojaBazaSonarQube';
- Jeśli nie, ustawiamy ją:
ALTER DATABASE TwojaBazaSonarQube SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;
- Jeśli uruchamiamy instancję SQL server lokalnie, warto pamiętać o ustawieniu konkretnego portu np. 1433.
SonarQube server
Jednym z wymagań jest instalacja i konfiguracja Java Oracle JRE 17 lub OpenJDK 17. Skorzystajmy z drugiej opcji (Ryc. 3).
Po rozpakowaniu w naszej wybranej lokalizacji konfigurujemy systemowe zmienne środowiskowe:
JAVA_HOME <ścieżka do rozpakowanego folderu> PATH <ścieżka do rozpakowanego folderu/bin> lub %JAVA_HOME%/bin SONAR_JAVA_PATH <ścieżka do rozpakowanego folderu/bin/java.exe> lub %JAVA_HOME%/bin/java.exe
Z oficjalnej strony SonarQube pobieramy najnowszą wersję community (Ryc. 4) i rozpakowujemy:
Konfiguracja polega na odkomentowaniu i ustawieniu odpowiednich parametrów w pliku conf/sonar.properties. W naszym przypadku to jedynie konfiguracja połączenia z bazą danych:
sonar.jdbc.username=<TwojaNazwaUżytkownikaDb> sonar.jdbc.password=<TwojeHasło> sonar.jdbc.url=jdbc:sqlserver://localhost:1433;databaseName=<TwojaBazaSonarQube>;encrypt=false
Scanner
Instalujemy globalnie niezbędne narzędzie do przeprowadzenia skanu przy pomocy komendy:
dotnet tool install dotnet-sonarscanner –global
Uruchomienie
Teraz, gdy mamy już wszystko zainstalowane oraz skonfigurowane, odpalmy instancję serwera SonarQube poprzez wykonanie skryptu z folderu instalacyjnego serwera:
bin\windows-x86-64\StartSonar.bat
W konsoli powinniśmy zobaczyć logi potwierdzające uruchomienie serwera (Ryc. 5):
Serwer Web UI SonarQube nasłuchuje domyślnie na porcie 9000 (można to zmienić w pliku sonar.properties), a credentiale, które musimy zmienić podczas pierwszego logowania, to admin/admin).
Najpierw stwórzmy projekt w SonarQube, wybierając opcję Manually (Ryc. 6), a następnie podając dane projektu (Ryc. 7):
Jako że wszystko do tej pory działo się lokalnie, również do skanu użyjemy kodu znajdującego się na localhost. Wobec tego sklonujmy repozytorium (Ryc. 8), które przygotowałem na cele tego artykułu i wybierzmy opcję Locally widoczną po stworzeniu projektu.
Istotne, żeby w projekcie testowym dodana była referencja do coverlet.collector, dzięki któremu możemy zebrać dane po przeprowadzeniu testów. Kolejne kroki to stworzenie tokena, który pozwoli na przeprowadzenie analizy oraz wybór rodzaju projektu – w naszym przypadku to .NET (Ryc. 9):
SonarQube podpowie nam, jakich komend powinniśmy użyć, aby przeprowadzić analizę. Domyślnie jednak nie proponuje wygenerowania pokrycia kodu, wobec tego rozszerzmy nieco propozycję (poniższe instrukcje dotyczą wersji Core .NET, a dla wersji .NET Framework proszę odnieść się do dokumentacji):
dotnet sonarscanner begin /k:"SonarTest" /d:sonar.host.url="http://localhost:9000" /d:sonar.token="TwojTokenZSonarQube" /d:sonar.cs.opencover.reportsPaths="**\coverage.opencover.xml" /d:sonar.qualitygate.wait=true dotnet build dotnet test --collect:"XPlat Code Coverage;Format=opencover" dotnet sonarscanner end /d:sonar.token=" TwojTokenZSonarQube "
Pierwsza linia skryptu powyżej odpowiada za start analizy, wskazując jednocześnie nazwę projektu, URL serwera, token oraz nazwę pliku raportu jaki zostanie wykorzystany w generowaniu raportu po stronie SonarQube. Drugiej komendy myślę, że nie trzeba tłumaczyć. Komenda trzeci odpala testy oraz generuje plik w formacie opencover o nazwie coverage.opencover.xml. Ostatnia komenda odpowiada za zakończenie analizy. Na naszym ekranie powinniśmy zobaczyć informacje o powodzeniu przeprowadzonej analizy (Ryc. 10):
Wracając do web UI (Ryc. 11), możemy w bardzo czytelnej formie przeglądnąć wszystkie problemy, które zostały wykryte podczas analizy:
Celem artykułu jest pokazanie, jak przeprowadzić analizę kodu, nie będę natomiast omawiał interfejsu web SonarQube i możliwości, jakie nam daje.
Warto jeszcze wspomnieć o dostępnym rozszerzeniu do Visual Studio o nazwie SonarLint, które pozwala nam m.in. na pracę w Connected Mode i bieżącą analizę naszego kodu. Po instalacji SonarLint należy skonfigurować go do użycia z naszym serwerem SonarQube. W pierwszej kolejności po stronie serwera musimy wygenerować User Token, klikając w My Account i wybierając zakładkę security (Ryc. 12):
Kolejnym i ostatnim już krokiem jest konfiguracja połączenia po stronie Visual Studio. Włączamy widok Team Explorer, klikamy Connect i podajemy URL naszego serwera oraz wcześniej wygenerowany User Token (Ryc. 13):
Teraz pozostaje kliknąć prawym przyciskiem na nasz projekt i wybrać opcję Bind. W okienku Error List w VS powinniśmy widzieć te same problemy, jak w web UI SonarQube (lokalnie tworzony jest taki sam ruleset, jak w profilach na serwerze i jest on zsynchronizowany) (Ryc. 14):
Podsumowanie
W artykule omówiłem narzędzie SonarQube, które służy do statycznej analizy kodu źródłowego w celu wykrycia błędów, wycieków pamięci, nieprawidłowych zastosowań zmiennych, nieefektywnych fragmentów kodu i innych problemów. Narzędzie to działa w oparciu o reguły analizy statycznej, które określają standardy kodowania i najlepsze praktyki.
SonarQube umożliwia programistom definiowanie i dostosowywanie własnych reguł analizy statycznej oraz dostarcza raporty o jakości kodu dla całego zespołu.
***
Jeżeli interesują Cię inne narzędzia wykorzystywane w branży IT, zobacz koniecznie więcej artykułów naszych ekspertów.
Świetny artykuł
Super!
super!!