Najlepsza praktyka dla testów jednostkowych w Magento 1.9

11

Prowadzę witrynę Magento 1.9 z kilkoma niestandardowymi modułami. Niektóre funkcje mają krytyczne znaczenie dla biznesu i wymagają pilnych testów jednostkowych. Np. Kalkulator ceny jednostkowej.

Zwykle tworzę w Symfony i naprawdę wolałbym jakoś używać PHPUnit (w / Composer), jeśli to w ogóle możliwe.

Niektóre funkcje są oparte na danych importowanych do kilku niestandardowych tabel bazy danych, więc wolałbym w jakiś sposób ładować urządzenia.

Dlatego szukam najlepszego podejścia do pisania testów jednostkowych. Z chęcią przyjmę tutoriale lub coś podobnego. Każda pomoc jest mile widziana.

cholerstwo
źródło

Odpowiedzi:

10

Jakiś czas temu napotkałem ten sam problem.

Zastanawiałem się nad użyciem modułu Ecomdev PHPUnit, ale uważam, że jest trudny w użyciu i słabo udokumentowany (ale nadal uwielbiam to, co robi Ivan i jego wielki wkład w ekosystem Magento).

Tak więc przy pomocy Vinai opracowałem następujący moduł ram testowych: https://github.com/digitalpianism/testframework

Pierwotnym celem były testy integracyjne, ale używam go również do testów jednostkowych. Możesz zobaczyć to w akcji tutaj: https://github.com/digitalpianism/easytoplinks/blob/master/app/code/community/DigitalPianism/EasyToplinks/Test/Unit/Block/Page/Template/LinksTest.php

Jeśli chodzi o urządzenia, używam wycofywania transakcji, aby uniknąć tworzenia przykładowych danych w bazie danych.

Raphael at Digital Pianism
źródło
To wygląda naprawdę obiecująco. Wypróbuję to. Dzięki.
frigg
13

Instalacja

Ponieważ Magento 1 nie używa kompozytora po wyjęciu z pudełka, nie sądzę, że robi to dużą różnicę, jeśli instalujesz phpunit za pomocą kompozytora lub po prostu pobierasz wersję phar .
Jeśli już używasz kompozytora do zarządzania innymi modułami lub bibliotekami stron trzecich w swojej witrynie, prawdopodobnie kompozytor ma sens. O ile nie użyjesz PHP7, będziesz ograniczony do starej wersji phpunit (dlatego podłączyłem do powyższej wersji 4.8).

Testy integracyjne vs / i / lub testy jednostkowe

Ponieważ Magento 1 jest tak ciężką aplikacją, sensowne jest rozdzielenie bootstrapu phpunit na jeden do integracji i jeden do testów jednostkowych.
Test startowy testu jednostkowego musi tylko zainicjować autoloader, podczas gdy test testowy integracji musi zainicjować całe środowisko aplikacji, w tym ładowanie konfiguracji i połączenie db.
Z tego powodu testy integracyjne w Magento działają o wiele wolniej niż testy jednostkowe (nawet bardziej niż w innych aplikacjach).

Bootstrapping Magento do phpunit

  • Autoloader Magento nie jest zgodny z PSR-0, ponieważ zgłasza wyjątek, jeśli nie może znaleźć pliku, w którym znajduje się klasa. To przerywa niektóre zastosowania class_existsphpunit. Istnieje kilka możliwych (jeśli nieuczciwych) obejść:

    • Wyrejestruj autoloader Magento, owijając \Varien_Autoload::autoload()dekorator, ignorując zgłoszone wyjątki, i zarejestruj opakowanie jako nowy autoloader. Ma to małą szansę na konflikty z bibliotekami stron trzecich, które rejestrują autoloadery i zależą od określonej kolejności autoloaderów.
    • Użyj niestandardowej procedury obsługi błędów, zawijając tę ​​wbudowaną w Magento 1. Niestandardowe procedury obsługi błędów połykają błędy wywołane przez autoloader Magento. Jest to rozwiązanie używane przez środowisko testowe Rafaela . To wydaje się być najbardziej kompatybilne z innymi rozszerzeniami innych firm.
    • Użyj metody włączania ścieżki włączenia, aby przesłonić, \Varien_Autoload::autoload()aby nie zgłaszać błędu, jeśli plik nie istnieje. Jest to jednak sprzeczne z kilkoma modułami, które również zastępują tę samą klasę. Sam nie stosuję tego podejścia.
  • Aby uniknąć błędów podczas uruchamiania sesji podczas testów, po prostu ustaw $_SESSON = []w bootstrap.

  • Ustaw niestandardowy obiekt odpowiedzi, Mage::app()->setResponse($testResponse)który rozszerza rzeczywisty, ale nie wysyła danych wyjściowych ani nagłówków.

  • Aby ponownie zainicjować Magento między testami integracji, które całkowicie zmieniają stan środowiska uruchomieniowego, użyj Mage::reset(); Mage::app(). Zauważ, że po tym procedura obsługi błędów będzie musiała zostać ponownie ozdobiona.

Lampy

W przypadku urządzeń DB zwykle używam standardowych modeli w metodach urządzeń do tworzenia urządzeń, np createSimpleProduct($sku). Jak powiedział Raphael, użyj setUp()i, tearDown()aby zawinąć test w transakcję, która zostanie przywrócona po teście (na przykład Mage::getSingleton('core/resource')->getConnection('default_setup')->beginTransaction()).

W przypadku urządzeń do konfiguracji sklepu zwykle używam tylko urządzeń w pamięci Mage::app()->getStore()->setConfig($path, $value).

EcomDev_PHPUnitRozszerzenie zapewnia także opcję tworzenia DB urządzeń za pomocą plików yaml, ale dla siebie znajdę te trudniejsze do utrzymania w porównaniu do lamp tworzonych za pomocą klas modelu. YMMV.

Test Doubles

Rejestr może być użyty do wstrzyknięcia podwaja testowe dla obiektów utworzonych przez Mage::getSingleton(), Mage::getResourceSingleton()i Mage::helper().
Niektóre inne obiekty centralne można ustawić Mage::app()(np. Żądanie).
Aby zastąpić klasy utworzone za pomocą podwójnych testów Mage::getModel()lub Mage::getResourceModel()z nimi, należy użyć niestandardowego opakowania obiektu konfiguracji . Zobacz ten przykład w ramce testowej Rafaela, w jaki sposób można to osiągnąć.

streszczenie

Po uruchomieniu Magento prawie wszystko można przetestować raczej ładnie. Bądź przygotowany na tworzenie głębokich prób ze względu na dużą liczbę łańcuchów metod używanych w podstawowym kodzie.
Mimo że konfiguracja jest zhackowana, działa dobrze i uważam, że testy dają mi dużo pewności i wartości, prawie porównywalne z zestawem testów dla aplikacji Symphony.

Vinai
źródło
Nigdy tego nie próbowałem, ale dlaczego nie skorzystać z Magento Test Framework? ( docs.magento.com/m1/ce/user_guide/magento/… )
Fra
3
Tak, próbowałem, ale to testy funkcjonalne (nie jednostkowe lub integracyjne), są powolne, złożone, a testy wydają się kruche i kruche. Podsumowując, czas spędzony z nim uważałem za marnotrawstwo.
Vinai
@ Vinai Wiem, że jest późno, ale ogólnie w kontrolerze są wywołania modeli i kolekcji, których podczas testowania nie będziemy potrzebować. Korzystam z twojego środowiska testowego (DigitalPianism) i tam możemy TestDouble modele, ale podczas wysyłania zapytania do akcji kontrolera, która z kolei korzysta z modelu, jak mogę wyśmiewać to wywołanie modelu / kolekcji?
arqam