Testowanie i lista komend

Goat grupuje najczęstsze operacje developerskie w skrypty .goat znajdujące się w katalogu herd/.

Zamiast ręcznie uruchamiać kolejne polecenia Dockera, generatora, migracji, testów czy narzędzi frontendowych, możesz opisać cały proces jako jeden powtarzalny workflow i uruchamiać go pojedynczą komendą.

Skrypty są wykonywane z wykorzystaniem warstwy izolacji Goat. Dzięki temu zależności i narzędzia wymagane przez projekt mogą działać w kontenerach, bez konieczności instalowania ich bezpośrednio na systemie hosta.

Takie podejście daje kilka korzyści:

  • ujednolica sposób uruchamiania projektu na różnych systemach operacyjnych,
  • ogranicza zależność od lokalnej konfiguracji komputera programisty,
  • pozwala kontrolować wersje Go, Node.js, przeglądarek i innych narzędzi,
  • ogranicza zakres zmian wykonywanych przez skrypty do zasobów udostępnionych przez projekt,
  • upraszcza uruchamianie tych samych procesów lokalnie i w CI.

Codzienna praca

Najczęściej używane polecenia:

CelPolecenie
Uruchomienie środowiska developerskiegogoat run:script --path=herd/dev.goat
Ponowne wygenerowanie aplikacjigoat re
Uruchomienie migracji bazy danychgoat run:script --path=herd/db/migrate.goat
Wyczyszczenie lokalnej bazy danychgoat run:script --path=herd/db/clean.goat
Uruchomienie pełnego zestawu testówgoat run:script --path=herd/test.goat
Synchronizacja tłumaczeńgoat run:script --path=herd/translate.goat

goat run:script

Polecenie run:script uruchamia wskazany plik .goat:

goat run:script --path=herd/dev.goat

Plik skryptu może opisywać cały proces składający się z wielu kroków, na przykład:

  • uruchomienia kontenerów,
  • przygotowania zależności,
  • wygenerowania kodu,
  • wykonania migracji,
  • uruchomienia testów,
  • zbudowania frontendu,
  • uruchomienia aplikacji.

Dzięki temu logika środowiska developerskiego pozostaje częścią projektu, zamiast być rozproszona pomiędzy dokumentację, lokalne skrypty i konfigurację komputerów poszczególnych programistów.

goat re

Polecenie:

goat re

ponownie uruchamia proces generowania aplikacji na podstawie aktualnego modelu oraz konfiguracji projektu.

Najczęściej użyjesz go po zmianach w:

  • modelu domeny,
  • definicjach encji,
  • relacjach,
  • konfiguracji generatora,
  • szablonach generowanego kodu.

Generator powinien wprowadzać zmiany w kontrolowany sposób, tak aby możliwe było dalsze ręczne rozwijanie wygenerowanej aplikacji.

Po regeneracji warto sprawdzić różnice w Git przed ich zatwierdzeniem.

Testowanie

Pełny zestaw testów uruchomisz poleceniem:

goat run:script --path=herd/test.goat

herd/test.goat definiuje kompletny proces weryfikacji aplikacji.

Przed uruchomieniem właściwych testów skrypt odtwarza wygenerowaną część projektu. Dzięki temu testowany jest kod odpowiadający aktualnemu modelowi aplikacji, a nie przypadkowy lokalny stan wygenerowanych plików.

Następnie uruchamiane są między innymi:

  • testy backendu w Go,
  • budowanie aplikacji frontendowej,
  • testy frontendu,
  • testy E2E z wykorzystaniem Playwright.

Tam, gdzie jest to możliwe, niezależne etapy mogą być wykonywane równolegle, co skraca czas całego procesu.

Powtarzalne środowisko testowe

Testy korzystają z kontenerów, aby ograniczyć różnice pomiędzy środowiskami programistów oraz CI.

Dotyczy to w szczególności takich komponentów jak:

  • Go,
  • Node.js,
  • npm,
  • przeglądarki wykorzystywane przez Playwright,
  • PostgreSQL,
  • dodatkowe narzędzia wymagane podczas budowania aplikacji.

Dzięki temu wynik testów nie powinien zależeć od tego, jaką wersję Node.js lub Go programista ma aktualnie zainstalowaną na swoim komputerze.

Jest to szczególnie istotne dla testów E2E, które często są wrażliwe na wersję przeglądarki i zależności systemowe.

Izolacja podczas testów i budowania

Uruchamianie narzędzi w kontenerach pełni również funkcję bezpieczeństwa.

Operacje takie jak:

npm install
npm test
npm run build

nie muszą być wykonywane bezpośrednio na hoście.

Kod wykonywany przez zależności działa wewnątrz kontrolowanego środowiska i otrzymuje dostęp tylko do zasobów udostępnionych przez Goat oraz konfigurację projektu.

Pozwala to ograniczyć między innymi ryzyko związane ze skryptami instalacyjnymi zależności, takimi jak preinstall, install czy postinstall.

Jednocześnie izolacja nie zastępuje kontroli zależności. Nadal warto:

  • przeglądać aktualizacje bibliotek,
  • używać lockfile,
  • kontrolować źródła zależności,
  • sprawdzać zmiany przed ich zatwierdzeniem.

Sprawdzanie zmian po generowaniu

Po wykonaniu:

goat re

lub pełnego procesu testowego warto sprawdzić zmiany:

git status
git diff

Dzięki temu można dokładnie zobaczyć, które elementy aplikacji zostały zmodyfikowane przez generator.

Jest to szczególnie przydatne podczas zmian modelu domeny. Zamiast traktować regenerację jako operację typu „nadpisz całą aplikację”, Goat pozwala pracować z wygenerowanymi zmianami podobnie jak ze zmianami wprowadzanymi ręcznie.

Do repozytorium możesz zatwierdzić wyłącznie te pliki, które rzeczywiście powinny znaleźć się w danym commicie.

Debugowanie skryptów

Jeżeli któryś z workflow nie zakończy się poprawnie, najpierw uruchom bezpośrednio odpowiadający mu skrypt.

Przykładowo problemy z migracją można odtworzyć za pomocą:

goat run:script --path=herd/db/migrate.goat

a problemy z testami:

goat run:script --path=herd/test.goat

Rozdzielenie procesów na mniejsze skrypty .goat ułatwia ustalenie, czy problem dotyczy:

  • generowania,
  • bazy danych,
  • backendu,
  • frontendu,
  • testów E2E,
  • konfiguracji środowiska.

Pomoc dla komend aplikacji

Wygenerowana aplikacja zawiera również własne CLI.

Po jego zbudowaniu możesz wyświetlić dokumentację poszczególnych poleceń za pomocą flagi --help.

Przykładowo:

myapp crud:doc:persist --help
myapp db:migrate --help
myapp serve --help

Warto korzystać z --help zamiast polegać wyłącznie na przykładach z dokumentacji, ponieważ pokazuje ono parametry dostępne w aktualnie używanej wersji aplikacji.

Przykład: crud:doc:persist

Polecenie:

myapp crud:doc:persist --help

wyświetla opcje pozwalające utworzyć lub zaktualizować dokument.

Dostępne parametry obejmują między innymi:

  • --lang,
  • --slug,
  • --title,
  • --description,
  • --body-markdown,
  • --body-markdown-file.

W przypadku większych treści wygodniejsze jest przekazanie pliku:

myapp crud:doc:persist \
  --lang=pl \
  --slug=testowanie \
  --title="Testowanie" \
  --body-markdown-file=./doc/testowanie.md

Dzięki temu treść dokumentacji może być przechowywana w repozytorium i synchronizowana z aplikacją przy pomocy CLI.

Wydania

Proces przygotowania nowego wydania opisuje plik:

RELEASING.md

Zawiera on procedurę obejmującą między innymi:

  • wybór i ustawienie nowej wersji,
  • przygotowanie wymaganych kluczy,
  • budowanie artefaktów,
  • uruchomienie testów,
  • weryfikację paczek,
  • publikację wydania.

Nie pomijaj pełnego zestawu testów przed publikacją.

Przed rozpoczęciem procesu wydania warto również sprawdzić:

git status

i upewnić się, że repozytorium nie zawiera przypadkowych lokalnych zmian.

Wydanie powinno być przygotowywane dopiero wtedy, gdy:

  • generator działa poprawnie dla aktualnego modelu,
  • testy backendu przechodzą,
  • frontend poprawnie się buduje,
  • testy E2E przechodzą,
  • konfiguracja środowiska docelowego została zweryfikowana,
  • wszystkie zmiany przeznaczone do wydania znajdują się w repozytorium.

Typowy workflow

W codziennej pracy najczęściej wystarczy następujący cykl:

# zmień model aplikacji
vim herd/_model.goat

# wygeneruj wynikające z niego zmiany
goat re

# sprawdź wygenerowany kod
git diff

# uruchom testy
goat run:script --path=herd/test.goat

# sprawdź finalny zakres zmian
git status

Taki sposób pracy pozwala zachować wyraźny podział odpowiedzialności:

model opisuje intencję, generator tworzy powtarzalny kod, testy weryfikują rezultat, a Git pozostaje ostatecznym źródłem informacji o tym, co rzeczywiście zmieniło się w projekcie.