Tworzę wtyczkę za pomocą TDD i jedną rzecz, której całkowicie nie testuję, są ... haki.
Mam na myśli OK, mogę przetestować wywołanie zwrotne haka, ale jak mogę sprawdzić, czy hak faktycznie się wyzwala (zarówno niestandardowe haki, jak i domyślne haki WordPress)? Zakładam, że niektóre kpiny pomogą, ale po prostu nie mogę zrozumieć, czego mi brakuje.
Zainstalowałem pakiet testowy z WP-CLI. Zgodnie z tą odpowiedzią , init
hak powinien wyzwolić, ale ... to nie robi; kod działa również w WordPress.
Z mojego zrozumienia, pasek ładujący jest ładowany jako ostatni, więc sensowne jest, aby nie uruchamiać init, więc pozostaje pytanie: jak, do cholery, powinienem sprawdzić, czy haki są wyzwalane?
Dzięki!
Plik bootstrap wygląda następująco:
$_tests_dir = getenv('WP_TESTS_DIR');
if ( !$_tests_dir ) $_tests_dir = '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';
function _manually_load_plugin() {
require dirname( __FILE__ ) . '/../includes/RegisterCustomPostType.php';
}
tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
require $_tests_dir . '/includes/bootstrap.php';
testowany plik wygląda następująco:
class RegisterCustomPostType {
function __construct()
{
add_action( 'init', array( $this, 'register_post_type' ) );
}
public function register_post_type()
{
register_post_type( 'foo' );
}
}
I sam test:
class CustomPostTypes extends WP_UnitTestCase {
function test_custom_post_type_creation()
{
$this->assertTrue( post_type_exists( 'foo' ) );
}
}
Dzięki!
źródło
phpunit
, czy widzisz testy zakończone niepowodzeniem lub pozytywnie? Czy zainstalowałeśbin/install-wp-tests.sh
?RegisterCustomPostType::__construct()
nigdy nie jest wywoływana, gdy wtyczka jest ładowana do testów. Możliwe jest również, że dotknął Cię błąd # 29827 ; może spróbuj zaktualizować swoją wersję pakietu testów jednostkowych WP.bin/install-wp-tests.sh
(ponieważ użyłem wp-cli) @JD: wywoływana jest konstrukcja RegisterCustomPostType :: __ (właśnie dodałemdie()
instrukcję i phpunit się tam kończy)did_action()
aby sprawdzić, czy działania zostały uruchomione.init
przechwyceniem).Odpowiedzi:
Testuj w izolacji
Podczas opracowywania wtyczki najlepszym sposobem na przetestowanie jej jest bez ładowania środowiska WordPress.
Jeśli napiszesz kod, który można łatwo przetestować bez WordPressa, Twój kod będzie lepszy .
Każdy komponent, który jest testowany jednostkowo, powinien być testowany osobno : podczas testowania klasy wystarczy przetestować tę konkretną klasę, zakładając, że cały inny kod działa idealnie.
Z tego powodu testy jednostkowe nazywane są „jednostkami”.
Dodatkową korzyścią jest to, że bez ładowania rdzenia test będzie przebiegał znacznie szybciej.
Unikaj haków w konstruktorze
Wskazówka, którą mogę ci dać, to unikanie wprowadzania haków do konstruktorów. To jedna z rzeczy, która sprawi, że Twój kod będzie testowany w izolacji.
Zobaczmy kod testowy w OP:
Załóżmy, że ten test się nie powiedzie . Kto jest winowajcą ?
Jak można to poprawić?
Załóżmy, że twój kod klasy to:
(Uwaga: w dalszej części odniosę się do tej wersji klasy)
Sposób, w jaki napisałem tę klasę, pozwala tworzyć instancje klasy bez wywoływania
add_action
.W powyższej klasie do przetestowania są 2 rzeczy:
init
faktycznie wywołujeadd_action
przekazanie jej odpowiednich argumentówregister_post_type
faktycznie wywołujeregister_post_type
funkcjęNie powiedziałem, że musisz sprawdzić, czy istnieje typ postu: jeśli dodasz odpowiednią akcję i zadzwonisz
register_post_type
, niestandardowy typ postu musi istnieć: jeśli nie istnieje, jest to problem WordPress.Pamiętaj: kiedy testujesz wtyczkę, musisz ją przetestować swój kod, a nie kod WordPress. W testach musisz założyć, że WordPress (podobnie jak każda inna zewnętrzna biblioteka, której używasz) działa dobrze. Takie jest znaczenie testu jednostkowego .
Ale ... w praktyce?
Jeśli WordPress nie jest załadowany, jeśli spróbujesz wywołać metody klas powyżej, pojawi się błąd krytyczny, więc musisz wyśmiać funkcje.
Metoda „ręczna”
Na pewno możesz napisać swoją kpiącą bibliotekę lub „ręcznie” kpić z każdej metody. To jest możliwe. Powiem ci, jak to zrobić, ale potem pokażę ci łatwiejszą metodę.
Jeśli WordPress nie jest ładowany podczas testów, oznacza to, że możesz przedefiniować jego funkcje, np .
add_action
Lubregister_post_type
.Załóżmy, że masz plik załadowany z pliku bootstrap, w którym masz:
Ponownie napisałem funkcje, aby po prostu dodać element do globalnej tablicy za każdym razem, gdy są wywoływane.
Teraz powinieneś utworzyć (jeśli jeszcze go nie masz) rozszerzenie swojej podstawowej klasy przypadków testowych
PHPUnit_Framework_TestCase
: pozwala to na łatwą konfigurację testów.Może to być coś takiego:
W ten sposób przed każdym testem licznik globalny jest resetowany.
A teraz twój kod testowy (odnoszę się do przepisanej klasy, którą zamieściłem powyżej):
Należy pamiętać:
Fajnie .. ale to PITA!
Tak, jeśli musisz ręcznie wyśmiewać wszystkie funkcje WordPressa, to naprawdę ból. Kilka ogólnych rad, których mogę udzielić, to korzystania z jak najmniejszej liczby funkcji WP: nie musisz przepisywać WordPress, ale abstrakcyjne funkcje WP, których używasz w niestandardowych klasach, aby można je było wyśmiewać i łatwo testować.
Na przykład w odniesieniu do powyższego przykładu możesz napisać klasę, która rejestruje typy postów, dzwoniąc
register_post_type
„init” z podanymi argumentami. Dzięki tej abstrakcji nadal musisz przetestować tę klasę, ale w innych miejscach kodu rejestrujących typy postów możesz skorzystać z tej klasy, kpiąc z niej w testach (zakładając, że działa).Niesamowite jest to, że jeśli napiszesz klasę, która streszcza rejestrację CPT, możesz stworzyć dla niej osobne repozytorium, a dzięki nowoczesnym narzędziom, takim jak Composer, osadzić ją we wszystkich projektach, w których jest to potrzebne: przetestuj raz, używaj wszędzie . A jeśli kiedykolwiek znajdziesz w nim błąd, możesz go naprawić w jednym miejscu i za pomocą prostego rozwiązania
composer update
wszystkie projekty, w których jest on używany.Po raz drugi: napisanie kodu, który można przetestować w izolacji oznacza napisanie lepszego kodu.
Ale wcześniej czy później muszę gdzieś użyć funkcji WP ...
Oczywiście. Nigdy nie powinieneś działać równolegle do rdzenia, to nie ma sensu. Możesz pisać klasy, które otaczają funkcje WP, ale klasy te również muszą zostać przetestowane. Metodę „ręczną” opisaną powyżej można stosować do bardzo prostych zadań, ale gdy klasa zawiera wiele funkcji WP, może to być uciążliwe.
Na szczęście są tam dobrzy ludzie, którzy piszą dobre rzeczy. 10up , jedna z największych agencji WP, utrzymuje bardzo dobrą bibliotekę dla osób, które chcą przetestować wtyczki we właściwy sposób. Jest
WP_Mock
.Pozwala wyśmiewać funkcje WP i haki . Zakładając, że załadowałeś w swoich testach (zobacz plik repo) ten sam test, który napisałem powyżej, wygląda następująco:
Proste, prawda? Ta odpowiedź nie jest tutorialem
WP_Mock
, więc przeczytaj plik repo, aby uzyskać więcej informacji, ale myślę, że powyższy przykład powinien być dość jasny.Co więcej, nie musisz pisać żadnych szydzonych
add_action
lubregister_post_type
samodzielnie, ani utrzymywać żadnych zmiennych globalnych.A zajęcia WP?
WP ma też pewne klasy, a jeśli WordPress nie jest ładowany podczas uruchamiania testów, musisz je wyśmiewać.
To o wiele łatwiejsze niż kpiące funkcje, PHPUnit ma wbudowany system do kpienia z obiektów, ale tutaj chcę zasugerować kpinę . Jest to bardzo potężna biblioteka i bardzo łatwa w użyciu. Co więcej, jest to zależność od
WP_Mock
, więc jeśli ją masz, masz także Kpinę.Ale co z
WP_UnitTestCase
?Pakiet testowy WordPress został stworzony do testowania rdzenia WordPress , a jeśli chcesz przyczynić się do rdzenia, jest on kluczowy, ale użycie go do wtyczek sprawia, że nie testujesz go osobno.
Spójrz na świat WP: istnieje wiele nowoczesnych frameworków PHP i CMS, a żaden z nich nie sugeruje testowania wtyczek / modułów / rozszerzeń (lub jakkolwiek są one nazywane) przy użyciu kodu frameworka.
Jeśli tęsknisz za fabrykami, przydatną funkcją pakietu, musisz wiedzieć, że są niesamowite rzeczy .
Gotcha i wady
Zdarzało się, że brakuje przepływu pracy, który zasugerowałem tutaj: niestandardowe testowanie bazy danych .
W rzeczywistości, jeśli użyć standardowych tabel WordPress i funkcje, aby tam pisać (na najniższym poziomie
$wpdb
metod) nie trzeba faktycznie zapisu danych lub testu, jeśli dane są rzeczywiście w bazie danych, po prostu mieć pewność, że odpowiednie metody są wywoływane z odpowiednimi argumentami.Możesz jednak pisać wtyczki z niestandardowymi tabelami i funkcjami, które budują zapytania, aby tam pisać i sprawdzać, czy te zapytania działają, to na twoją odpowiedzialność.
W takich przypadkach pakiet testowy WordPress może ci bardzo pomóc, a ładowanie WordPress może być w niektórych przypadkach konieczne do uruchomienia takich funkcji
dbDelta
.(Nie trzeba mówić, że do testów używa się innej bazy danych, prawda?)
Na szczęście PHPUnit umożliwia organizowanie testów w „pakietach”, które można uruchamiać osobno, dzięki czemu możesz napisać zestaw niestandardowych testów bazy danych, w których ładujesz środowisko WordPress (lub jego część), pozostawiając wszystkie pozostałe testy bez WordPressa .
Pamiętaj tylko, aby pisać klasy, które wyodrębniają jak najwięcej operacji bazy danych, w taki sposób, aby wszystkie inne klasy wtyczek korzystały z nich, aby za pomocą prób można poprawnie przetestować większość klas bez zajmowania się bazą danych.
Po raz trzeci pisanie kodu łatwo testowalnego w izolacji oznacza pisanie lepszego kodu.
źródło