Dlaczego automatyzujemy tworzenie oprogramowania

Automatyzacja tworzenia oprogramowania

Jedną z wyznawanych przez nas w Droptica wartości jest jakość. Chcemy tworzyć jak najlepsze programy, spełniające przy tym wymagania klienta: działające, wolne od błędów,  opłacalne. Dziś napiszę o jednym z bardzo ważnych czynników wpływających na jakość powstającego oprogramowania - mianowicie o automatyzacji procesu tworzenia oprogramowania.

W naszej agencji drupalowej jesteśmy zdecydowanymi orędownikami automatyzacji. Przez ostatnie 10 lat mieliśmy przyjemność pracować z wieloma klientami przy bardzo różnych projektach i w zróżnicowanych zespołach. Zawsze intensywnie lobbowaliśmy za jak największą automatyzacją oraz jak największym zbliżaniem się do Continuous Integration, często ratując projekt przed bardzo poważnymi konsekwencjami.

Zanim jednak opiszę korzyści wynikające z automatyzacji, wytłumaczę, na czym polega.

Automatyzacja tworzenia oprogramowania

Zautomatyzowany proces tworzenia oprogramowania wyróżniają następujące cechy:

1. Ustanowione jest jedno wspólne repozytorium kodu. Wszyscy programiści przekazują wytworzony kod poprzez repozytorium kodu. Obecnie najpopularniejszym oprogramowaniem do repozytorium jest git. Kod w repozytorium jest jedynym źródłem oprogramowania w projekcie. Nie ma żadnych dodatkowych skryptów, programów lub innych kodów wysyłanych mailem czy dystrybuowanych w zespole w inny sposób.

2. Istnieje tzw. "build process". Build process jest to standaryzowana metoda stawiania/tworzenia kopii oprogramowania. Każdy programista, tester, skrypt testowy czy mechanizm wykorzystuje ten sam proces do uzyskiwania bieżącej wersji oprogramowania.

3. Build process jest zautomatyzowany. Uzyskanie bieżącej wersji oprogramowania nie wymaga wykonywania wielu manualnych czynności. Idealnym stanem jest, gdy build process jest skryptem/programem, który również podlega kontroli wersji w repozytorium kodu. Programista pobiera najnowszy kod z repozytorium, wywołuje proces budowania (np. odpala skrypt) i otrzymuje bieżący stan aplikacji. Ten sam skrypt jest wykorzystywany przez narzędzia testujące, środowiska testowe czy jest wykorzystywany do tworzenia wersji demonstracyjnych.

4. Build jest szybki. Budowanie oprogramowania trwa na tyle szybko, że można wielokrotnie sprawdzać rezultaty i wprowadzać poprawki.

5. Zespół wysyła zmiany często, najlepiej codziennie lub kilka razy dziennie. Działający kod jest na bieżąco wciągany na główną gałąź w systemie kontroli wersji.

6. Środowisko testowe powinno jak najbardziej odpowiadać w środowisku produkcyjnym. W idealnych warunkach będzie to wierna kopia środowiska produkcyjnego.

7. Proces wdrażania oprogramowania na produkcję jest zautomatyzowany. Najlepiej, jeśli wywołanie wdrożenia nowych zmian na produkcję odbywa się poprzez "naciśnięcie jednego guzika" czy wywołanie jednego skryptu.


W momencie, gdy osiągniemy powyższe punkty, już uzyskujemy bardzo wiele korzyści wprowadzających porządek w procesie tworzenia oprogramowania:

1. Możemy błyskawicznie odtwarzać środowiska developerskie. Jednym z największych problemów projektów nieposiadających dobrej automatyzacji jest ciągły, nieustanny rozjazd pomiędzy tym, jak wygląda i działa oprogramowanie na produkcji, w środowisku developerskim i testowym. Przez to, że trzeba ręcznie przenosić zmiany między środowiskami, jest to robione rzadko lub nigdy. Na każdym środowisku powstają jakieś rzeczy specyficzne dla środowiska. Jeśli środowisk jest wiele, to problem jeszcze się nasila. Ryzyko, że kod lub konfiguracja stworzone w jednym środowisku będą inaczej działać w drugim, jest duże. Automatyczne szybkie regularne odbudowywanie środowisk eliminuje ten problem.

2. Jest jedno źródło prawdy o tym, jak wygląda bieżący stan projektu: Build. Zbudowanie oprogramowania poprzez build daje nam prawdziwy obraz tego, jak wygląda i działa kod. Ocena rezultatów prac jest jednoznaczna. Nie ma problemów typu: “U mnie działało” lub “Na dev działa a na test już nie”. Zbudowany na świeżo, automatycznie projekt jest jedynym, jaki podlega ocenie.

3. Możemy wielokrotnie "budować" oprogramowanie i testować wdrożenie w środowisku testowym aż uzyskamy pożądany efekt i pewność, że po wdrożeniu osiągniemy przewidywalne rezultaty oraz że wdrożenie przebiegnie w przewidywalny sposób.

Ujmując korzyści automatyzacji buildu innymi słowami, można powiedzieć, że:
1. "Wiemy co mamy" - mamy pewność, co jest naszym bieżącym stanem.
2. Wszyscy pracują na tej samej wersji.
3. Jest jeden obiektywny sposób sprawdzania, czy coś działa czy nie.

Już to ratuje nas przed losem wielu zespołów, które marnują ogromną ilości czasu, sprawdzając, dlaczego na jednym środowisku działało, a po przeniesieniu na inne nie działa. Albo próbując w środowisku developerskim lub lokalnym odtworzyć błędy ze środowiska testowego.

Automatyczny build to jednak pół sukcesu. Drugie pół to testy

Automatyczne testowanie

Dzisiejsze oprogramowanie jest bardzo skomplikowane. Często są to setki tysięcy linii kodu rozrzucone po wielu plikach. Skomplikowane projekty używają wielu bibliotek i innych zależności. Zmiany dokonywane w kodzie oraz zmiany w bibliotekach mają często wpływ na działanie wielu funkcjonalności w systemie.

Programista, dokonując zmian, sprawdza z reguły czy poprawnie realizują one postawione przed nim zadanie. Często jednak nie ma ani wiedzy, ani możliwości sprawdzenia, czy jego zmiany nie wpływają na inne funkcjonalności systemu, na którym pracuje. Również testerzy, sprawdzając nowe funkcjonalności, nie są w stanie sprawdzić za każdym razem całego złożonego systemu, aby upewnić się, że gdzieś nie wkradły się błędy.

W przypadku braku testów automatycznych typowym zabezpieczeniem przed wprowadzeniem błędów na produkcję jest testowanie całego oprogramowania przed jego wdrożeniem. Jest to jednak syzyfowa praca. Każdy znaleziony i poprawiony błąd wymaga zmian w kodzie, a więc wymaga też przeprowadzenia ponownych testów całego systemu. Bardzo często taka praktyka powoduje długą spiralę testów, błędów, testów i nowych błędów lub niedokładne testy i wprowadzanie błędów na produkcję.

Rozwiązaniem tego problemu są automatyczne testy. Jest wiele metodyk tworzenia testów i testowania oprogramowania. Nie będziemy ich tu wymieniać, a opiszemy tylko jakie cechy powinny mieć:

1. Testy powinny być automatyczne. Ich wywołanie powinno być proste. Każdy programista powinien być w stanie wywołać wszystkie testy w swoim środowisku programistycznym.

2. Testy powinny być szybkie. Długość trwania testów nie powinna powodować, że się je pomija. Powinny być przeprowadzane za każdym razem, gdy dokonuje się zmian w oprogramowaniu. Idealnym stanem jest osobne testowanie każdego commitu, a na pewno powinno się testować każdy kod, który ma być wciągnięty na główną gałąź.

3. Testy powinny pokrywać możliwie jak największą część oprogramowania. Testów powinno być tyle i powinny być tak rozplanowane, aby wszystkie istotne funkcje oprogramowania były przetestowane. Zespół powinien mieć pewność, że jeśli wszystkie testy przeszły poprawnie, to znaczy, że oprogramowanie działa poprawnie. Są różne techniki szacowania pokrycia kodu testami, które można wykorzystywać, aby mieć kontrolę nad ilością testów.

4. Testy powinny być częścią builda. W idealnej sytuacji każdy build automatycznie odpala wszystkie testy i wyświetla ich wyniki.

5. Każda zmiana powinna być sprawdzona poprzez przetestowanie całego systemu. Idealną sytuacją jest, jeśli testujemy każdy commit, ale ostatecznie wystarczy testowanie kodu przed włączeniem go do głównej gałęzi. Jeśli programista wyśle do głównej gałęzi kod psujący oprogramowanie, utrudnia on pracę wszystkim innym, którzy w danym momencie próbują rozpocząć pracę nad nowym zadaniem startując z najnowszego build’a (bo ten nie działa, gdyż kod zawiera błąd). Zespoły niemające automatycznych testów bardzo często zderzają się z  problemem, że jakiś nowy commit psuje działanie części oprogramowania i wszyscy, którzy chcieli akurat na niej pracować, są wstrzymani, aż błąd zostanie naprawiony. Automatyczne testy zapobiegają podobnej sytuacji.

Automatyczne budowanie i automatyczne testy to klucz do sukcesu

Jeśli zautomatyzujemy proces wytwarzania oprogramowania wraz z używaniem automatycznych testów, otrzymamy mechanizm, w którym zawsze wiemy jaki stan oprogramowania mamy. Co ważne, przed dodaniem jakichkolwiek nowych zmian, możemy sprawdzić, czy nie wprowadzają one nowych błędów. Dzięki temu możemy prawie w każdej chwili zdecydować się na wdrożenie bieżącej wersji oprogramowania na produkcję. Do tego zrobimy to szybko i bezpiecznie, bo zrobi to za nas automatyczny proces, który przetestowaliśmy wcześniej w środowisku testowym identycznym z produkcyjnym.

Osiągając ten poziom automatyzacji, możemy bez obawy tworzyć nowe funkcjonalności. wiedząc, że na pewno działają i nic nie psują oraz wykonywać wdrożenia. Pozbywamy się ryzyka, że coś zepsujemy. A jeśli znajdziemy błąd, możemy go szybko naprawić.

Nasze doświadczenia

W Droptica zajmujemy się przede wszystkim Drupal developmentem i wsparciem Drupala, a każdy projekt, który przejmujemy lub rozpoczynamy, staramy się realizować w jak największej zgodzie z powyższą metodyką.

Zazwyczaj nakłady poniesione na tworzenie testów zwracają się bardzo szybko. Ilość testów manualnych koniecznych przed wdrożeniem spada dramatycznie, rekompensując poniesione koszty. Testy automatyczne powodują, że błędy wychwytywane są o wiele szybciej. Często, jeśli zaczynamy tworzyć testy automatyczne na projekcie, który wcześniej ich nie posiadał, znajdują one wiele błędów, o których wcześniej nikt nie miał pojęcia.

Zespół przestaje walczyć z błędami, a znacznie więcej czasu poświęca na tworzenie oprogramowania. Automatyzacja przekłada się na większe zadowolenie i pewność klienta, o wiele szybsze czasy “od zgłoszenia do wdrożenia” oraz większą satysfakcję zespołu z wykonywanej pracy.
Jeśli automatyzacja jest dobrze wdrożona i testy są poprawnie napisane, nasi programiści Drupala mogą wykonywać wdrożenia nawet kilka razy dziennie, albo w z góry ustalonym harmonogramie (np. raz w tygodniu) bez ryzyka, że zepsujemy produkcję. Co ważne, nie poświęcimy na wdrożenie dużo czasu.

W ramach wsparcia dla Drupala utrzymujemy istniejące strony internetowe i rozbudowujemy je o nowe funkcjonalności