Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup cypress #932

Merged
merged 8 commits into from
Nov 4, 2020
Merged

Setup cypress #932

merged 8 commits into from
Nov 4, 2020

Conversation

rwakulszowa
Copy link
Member

#741

Szkielet + prosty test renderujący główną stronę. Póki co nie dodawałem żadnych "ciekawych" testów - wolę poświęcić na to oddzielny PR, żeby nie komplikować.

W przeszłości używałem podejścia w którym testy integracyjne startowane są z użyciem docker-compose. Ma to tę zaletę, że jest bardzo proste w obsłudze dla użytkownika, który chce tylko sprawdzić kompatybilność wprowadzonych zmian, bez zmian konfiguracji samych testów (innymi słowy, nie trzeba znać się ani na docker-compose, ani na cypress, żeby wystartować testy).

Jeśli wygląda ok, mogę przy okazji tego PR dodać też integrację z GitHub Actions.
Pytanie czy chcemy mieć testy w ramach istniejącej akcji (web), czy oddzielnej. Prawdopodobnie na dłuższą metę dodanie ich w jeden ciąg miałoby sens, ale obecnie akcja web zdaje się nie być bezstanowa (db i web są startowane wcześniej i pozostają aktywne do końca trwania akcji, o ile rozumiem), co może odrobinę zakłócać przebieg testów - prawdopodobnie wszystko zadziała, ale możemy nie wykryć, że testy przechodzą jedynie jeśli db zostanie wystartowana parę minut wcześniej, co może być odrobinę zaskakujące.

@rwakulszowa rwakulszowa requested a review from ad-m October 31, 2020 15:23
@@ -88,6 +88,12 @@
)
# END MIDDLEWARE CONFIGURATION

# SITE CONFIGURATION
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Przeniesione z production.py.

W trybie development, domyślnie dopuszczone są wartości localhost i pokrewne. Test cypress wymaga dopuszczenia hosta web.

Jako, iż produkcyjna wartość jest już ustawiona na "*", najprostszym rozwiązaniem było użycie tego samego mechanizmu dla środowiska dev.

tests/README.rst Outdated

HowTo
=====
Testy najłatwiej wywołać używając pliku docker-compose.test.yml.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zastanawiam się czy dokumentacja takiego rodzaju nie powinna być widoczna (co najmniej) także przez Sphinx, który mamy.

@ad-m
Copy link
Member

ad-m commented Oct 31, 2020

#741

Szkielet + prosty test renderujący główną stronę. Póki co nie dodawałem żadnych "ciekawych" testów - wolę poświęcić na to oddzielny PR, żeby nie komplikować.

W pełni podzielam podział tego na etapy.

W przeszłości używałem podejścia w którym testy integracyjne startowane są z użyciem docker-compose. Ma to tę zaletę, że jest bardzo proste w obsłudze dla użytkownika, który chce tylko sprawdzić kompatybilność wprowadzonych zmian, bez zmian konfiguracji samych testów (innymi słowy, nie trzeba znać się ani na docker-compose, ani na cypress, żeby wystartować testy).

W taki sposób zmierzam w projekcie do testów i jest to spójne, więc popieram.

Jeśli wygląda ok, mogę przy okazji tego PR dodać też integrację z GitHub Actions.
Pytanie czy chcemy mieć testy w ramach istniejącej akcji (web), czy oddzielnej. Prawdopodobnie na dłuższą metę dodanie ich w jeden ciąg miałoby sens, ale obecnie akcja web zdaje się nie być bezstanowa (db i web są startowane wcześniej i pozostają aktywne do końca trwania akcji, o ile rozumiem), co może odrobinę zakłócać przebieg testów - prawdopodobnie wszystko zadziała, ale możemy nie wykryć, że testy przechodzą jedynie jeśli db zostanie wystartowana parę minut wcześniej, co może być odrobinę zaskakujące.

Odnośnie bezstanowości to wykonywanie testów jest bezstanowe, z perspektywy bazy danych i systemu plików, bo wykorzystujemy testy Django, które tworzą osobną bazę danych dla testów, którą potem usuwają. web nie jest startowany, a jedynie budowany, bo środowisko web służy – oprócz serwowania aplikacji – do uruchamiania testów.

@@ -0,0 +1,7 @@
// The simplest tests, validating that it's possible to render the app at all.
describe('landing page', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jak będziemy provisionować stan aplikacji (faza setup), skoro JavaScript?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jeśli mam być szczery, to moje doświadczenie z cypress nie jest duże, ale wiem że istnieje możliwość wywołania dowolnej komendy z użyciem cy.exec. W takiej sytuacji kod testu (najprawdopodobniej) będzie mógł komunikować się bezpośrednio z bazą poprzez dedykowane skrypty.

Copy link
Member

@ad-m ad-m Oct 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ja także nie mam dużego doświadczenia w testowaniu front-endu, a w zakresie aplikacji Python & testy Javascript nie mam doświadczenia żadnego. Jeżeli będziemy używać cy.exec to pozostanie kwestia odpowiedniego zarządzania tymi skryptami (napisanymi w Pythonie). Dołożyłeś nowy kontener bazujący na cypress, więc wywołanie z niego Pythona nie będzie trywialne.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raczej miałem na myśli wywołanie skryptów napisanych też w JS, gadajacych bezpośrednio z bazą danych. Testy byłyby zdefiniowane w tym samym kontenerze co testy.

Generalnie nie spodziewam się, przynajmniej póki co, wywoływania niczego bardziej skomplikowanego niż usunięcie wszystkich danych przed testem, ewentualnie stworzenie możliwości dodania paru kluczowych obiektów. Raczej parę podstawowych, łatwych w utrzymaniu skryptów JS.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Możemy spróbować, ale rezygnowanie z fabryk, które mamy na back-endzie wywołuje moje obawy w zakresie kosztów rozwoju i utrzymania. Obecnie większość stanu jesteśmy w stanie zrobić jednym wywołaniem fabryki, ewentualnie odpowiednim wywołaniem ORM-a. Uważam to za dużą wartość i ułatwienie w pisaniu testów. Tu proponujesz zejście z tych warstw na najniższy poziom.

Co zdecydowało o wyborze Cypress do testów? Rozważałeś klasyczne Selenium, które mniej modne, ale mogłoby nam zapewnić bliższą integracje z tym co dotychczas mamy ( https://blog.mloza.pl/testy-w-django-z-uzyciem-selenium/ ), albo coś w Pythonie np. Pyppeteer / Splinter?

Copy link
Member Author

@rwakulszowa rwakulszowa Nov 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cóż, główny problem z Selenium jest taki, że to bardzo stara technologia, więc o ile byłoby to prostsze w kwestii pisania samych testów (Python), to spodziewałbym się problemów z utrzymaniem, z racji wieku biblioteki.

Wydaje mi się, że problemem tutaj nie jest kwestia użycia Cypress / Selenium, ale kwestia umieszczenia testów w oddzielnym kontenerze. Z cypress mamy dostęp do basha, więc gdyby był w tym samym kontenerze co django, mógłby po prostu wywołać dowolny skrypt py i rozwiązać problem.
Wydaje mi się jednak, że umieszczenie testów integracyjnych w oddzielnym kontenerze ma więcej zalet niż wad. Koniec końców, chcemy by testy były jak najbliższe rzeczywistości, więc komunikacja bezpośrednio z django / bazą powinna być ostatecznością.
Co do samych testów - raczej zakładam, że doprowadzenie aplikacji do konkretnego stanu powinno być częścią samego testu, a nie kodu wykonywanego przed nim, tj.:

  • jeśli chcemy testować edycję spraw, w ramach testu powinniśmy wywołać
    1. logowanie / rejestrację użytkownika
    2. utworzenie kilku spraw
    3. aktualizację konkretnej sprawy

To oczywiście zwiększy czas trwania testu, ale wykryje więcej potencjalnych błędów. Nie mamy pewności, czy wywołując ręcznie factory django nie pomijamy czegoś co wydarza się po przeklikaniu w przeglądarce, a to właśnie chcemy przetestować.

Ręczna komunikacja z bazą danych (i ogólnie z bashem) mogłaby ograniczyć się do:

  1. sprzątania bazy po każdym teście
  2. ewentualnego ustawienia wartości, których obecnie nie można przeklikać (np. teryt)
  3. obsługi komunikacji, która w praktyce odbywa się poza przeglądarką (np. email - nie wiem dokładnie jak wygląda implementacja, ale zakładam, że - przynajmniej w jakimś stopniu - można zastąpić emaile bezpośrednią komunikacją z bazą).
    Innymi słowy, rzeczami, które nie będą (za bardzo) wymagały znajomości modeli Django.

@rwakulszowa
Copy link
Member Author

Odnośnie bezstanowości to wykonywanie testów jest bezstanowe, z perspektywy bazy danych i systemu plików, bo wykorzystujemy testy Django, które tworzą osobną bazę danych dla testów, którą potem usuwają. web nie jest startowany, a jedynie budowany, bo środowisko web służy – oprócz serwowania aplikacji – do uruchamiania testów.

Ok, w takim razie po prostu dodam kolejny krok do istniejącej definicji.

@ad-m ad-m merged commit 5a4469f into watchdogpolska:master Nov 4, 2020
@ad-m
Copy link
Member

ad-m commented Nov 4, 2020

Dziękuje, wygląda nieźle :) W praktyce sprawdzimy UX podczas pisania testów.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants