Smoke Testing

Elaboration

Smoke testing is a superficial level of testing conducted by developers to make sure that all the functions of application work. They do not go into the finer details of the app, focusing rather on the major functionalities. Smoke tests can be either executed manually or be automated.
Typically these tests are run after the deployment process to check application status and in the worst case can trigger process responsibility for rollback application to the previous version. The major mission of smoke test tests is exposing integration issues and uncovering problems early. Also, it provides some level of confidence that changes to the software have not adversely affected major areas.

My solution

In my repository (https://github.com/tarnawski/smoke-test) you can find a prepared configuration for Behat (http://docs.behat.org) and Behat API Extension (https://behat-api-extension.readthedocs.io) which help with the automatic testing. Sample tests are located in the /feature folder.

Here an example test case wrote using Gherkin language:

Feature: Checking the Associator API operation
  In order check application work correctly
  As a client
  I need to get application status

  Scenario: Get status of application
    Given the "Content-Type" request header contains "application/json"
    When I request "/v1/status"
    Then the response code is 200
    And the response body contains JSON:
    """
    {
      "status": "Success",
      "version": "1.0"
    }
    """

 

Locally you can run the tests with one command using Docker containers:

docker run --rm --interactive --tty --volume $PWD:/app composer install && bin/behat

But please! Automate your work! You can use GitLab CI for this:

image: composer:latest

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
  - vendor/

before_script:
- composer install --no-progress --no-suggest

smoke-tests:
  script:
  - bin/behat -f progress

 

Jak czytać i interpretować wybrane metryki statycznej analizy kodu?

Lines of code (LOC):

Opis:
Mierzy ilość linii kodu w rozpatrywanym typie.
Interpretacja:
Metryka ta może być używana jako wskaźnik za dużych metod i klas.

Comment lines of code (CLOC):

Opis:
Ilość linii komentarza.
Interpretacja:
Niska wartość może wskazywać na niedostateczne udokumentowanie kodu.

Halstead’s volume (V)

Opis:
Opisuje rozmiar implementacji algorytmu. Obliczanie V jest oparte na ilości wykonanych operacji i operandów przetwarzanych w algorytmie.
Interpretacja:
V funkcji powinna być zawarta pomiędzy 20 a 1000. Objętości wyższe niż 1000 dają do zrozumienia że funkcja prawdopodobnie robi zbyt dużo rzeczy. V pliku powinna być zawarta między 100 i 8000.

Comment Weight (CW)

Opis:
Stosunek między kodem logicznym a komentarzem.
Interpretacja:
Niska wartość stosunku między kodem logicznym, a komentarzem może wskazywać na niedostateczne udokumentowanie kodu.

Cyclomatic complexity (CC)

Opis:
Złożoność cyklomatyczna, metryka używana do obliczania złożoności metod lub procedur.
Uproszczona wersja metryki: CC = d +1
Gdzie: d – liczba węzłów decyzyjnych w grafie (w praktyce liczy się ilość instrukcji if, while, do, for, ?:, catch, switch, case i operatorów &&, ||).
Interpretacja:
Wysokie wartości metryki CC wskazują na to, że metoda jest zbyt skomplikowana, przez co zwiększa się prawdopodobieństwo wystąpienia błędu. Wartości 1-4 są uważana za dobre, 8-10 jako zalecane do refaktoryzacji, powyżej 11 konieczna jest refaktoryzacja.

Lack of Cohesion in Methods (LCOM)

Opis:
Jest to metryka mierząca spójność metod wewnątrz klasy.
Interpretacja:
Wysoka wartość metryki może wskazywać klasy, które mają przydzieloną zbyt dużą ilość obowiązków i są kandydatem do podziału na mniejsze. Klasa o wysokiej wartości LCOM może być bardziej narażona na błędy, jest trudniejsza w testowaniu.

Afferent coupling (Ca):

Opis:
Ca to liczba klas spoza rozpatrywanego pakietu, które zależą od klas w rozpatrywanym pakiecie.
Interpretacja:
Wysoka wartość tej metryki sugeruje w niejawny sposób dużą stabilność komponentu, ale także dużą odpowiedzialność względem zależnych typów.

Efferent coupling (Ce):

Opis:
Ce to liczba klas z rozpatrywanego pakietu, które zależą od klas w innych pakietach. Mierzy zatem podatność rozpatrywanego pakietu na zmiany w pakietach, od których zależy.
Interpretacja:
Wysokie wartości tej metryki wskazują na niestabilność pakietu – duża zależność od zewnętrznych klas.

Instability (I):

Opis:
I jest to względna podatność na zmiany. Metryka ta jest zdefiniowana za pomocą Ce i Ca.
Interpretacja:
Pakiety powinny się dzielić na dwie grupy:
– stabilne o wartości metryki I bliskiej 0, które ponoszą dużą odpowiedzialność
wobec innych komponentów.
– niestabilne o wartości metryki I bliskiej 1, które w dużej mierze zależą od
innych komponentów.

Analiza statyczna kodu

Analiza statyczna kodu – analiza struktury kodu źródłowego lub kodu skompilowanego bez jego uruchomienia.

Zastosowania:
– automatyczna ocena zmian w kodzie
– szybka, wstępna analiza otrzymanego projektu
– uzyskiwanie informacji o zgodności kodu z narzuconymi standardami
– wspieranie procesu code review
– wykrywanie słabych punktów projektów – miejsc wymagających refaktoryzacji.

Zalety:
– Szybkość działania – szybkie wykrywanie błędów, których naprawa jest prosta i mało kosztowna
– nie wymagają uruchamiania programu
– łatwe do zrównoleglenia
– Łatwość użycia – proste we wdrożeniu w cykl wytwarzania oprogramowania
– Automatyzacja – integracja z narzędziami continuous integrations
– Możliwości rozszerzania: własne reguły, wtyczki
– Dużo darmowych narzędzi
– Integracja z innymi narzędziami: serwery automatyzacji, IDE, kontrola wersji

Wady:
– Wymagany dostęp do źródeł
– Reguły wykrywają zazwyczaj proste błędy i nie są w stanie wyeliminować ręcznego sprawdzenia kodu
– Dużo szumu, zbyt czułe – duże prawdopodobieństwo zaklasyfikowanie poprawnego fragmentu jako błędu (false positive)
– Skomplikowane algorytmy i architektury bardzo ciężko jest analizować
– Każde narzędzie zazwyczaj pokrywa pewien zakres testów (do 14% błędów?!). Dlatego warto korzystać z kilku różnych skanerów kodu

Dlaczego analizować kod?
– zwiększenie wydajności i stabilności poprzez zasady oparte na dobrych praktykach,
– uniknięcie typowych błędów podczas programowania,
– dostarczenie struktury do zarządzania standardami kodu.
– wymuszenie zasad i standardów pisania kodu
– zwiększenie bezpieczeństwa poprzez kolejny etap testowania
– analizując sygnalizowane błędy można się sporo nauczyć na temat dobrych praktyk bezpiecznego programowania