2010-12-28 19 views
10

Pozdrowienia Stackoverflowers,Gniazda do testowania urządzeń

Mam aplikację, w której istnieje warstwa abstrakcji komunikacji. Każda implementacja w tej warstwie, o nazwie ,, zapewnia mojej aplikacji sposób wymiany danych z podłączonym urządzeniem równorzędnym (np .: poprzez HTTP, gniazda TCP, gniazda UDP itp.).

Na przykład, mam Connector_Tcp klasy, która implementuje metody takie jak odczytane, zapisu, otwarty i bliską.

Potrzebuję napisać test jednostkowy dla tej klasy. Wiem, że testy jednostkowe powinny mieć jak najmniej zależności. Niestety, w tym przypadku zależność jest zasobem systemowym: gniazdem; i nie mogę tego obejść.

Potrzebuję porady, jak postępować w sprawie testowania jednostki tej klasy.

Moim zdaniem, chociaż ta klasa jest użycie zasobów systemowych, powinno być badane jak wszystkie inne złączy aby upewnić się, że nie narusza normę ustaloną przez mojego wniosku.

Obawiam się, że takie rzeczy jak kolizje wiążące (Adres już w użyciu błędy) i blokowanie. Nie chcę, aby test jednostki zakończył się niepowodzeniem, ponieważ port jest już używany przez usługę systemową, która nie ma nic wspólnego z moją aplikacją.

W moich czasach wykonałem wiele testów jednostkowych, ale żadna z nich nie opiera się na takich zasobach niskiego poziomu, które są gniazdami.

Co powiesz na testowanie jednostki w klasie zależnej od gniazda? Otworzyć gniazdo dla każdej jednostki? Użyj klasy pojedynczego serwera, a następnie ręcznie zdefiniowanego zasobu gniazda, aby się z nim połączyć i przetestować ...?

Chyba naprawdę mój problem jest następujący:

Jeśli test nie powiedzie się jednostka ... Jak mogę sprawdzić, czy:

  • Gniazdo jest już używany przez inny proces;
  • Test jednostkowy jest źle napisany; lub
  • Metoda zachowuje się niepoprawnie (co jest wartością testu jednostkowego).

muszę testów jednostkowych do testowania tylko wtedy, gdy metoda została zachowuje się prawidłowo, czy nie ...

+1

Nie zrobiłem żadnego prawdziwego rozwoju PHP, ale czy możesz stworzyć fałszywą klasę wywodzącą się z twojej klasy Socket? – Dave

+0

@Dave: Mogę. Używam symulowanych obiektów dla każdej klasy, która wymaga złącza. Mój problem tutaj: muszę przetestować samą klasę socket, aby upewnić się, że respektuje konwencje warstwy abstrakcji ... Testując próbny obiekt, nie mówi mi jednoznacznie, czy klasa gniazda działa, czy nie. – netcoder

+0

Istnieje praktyczna granica tego, co można testować jednostkowo w mojej opinii. Nie próbowałbym testować gniazda w urządzeniu. Przypuszczam, że w twoim przypadku, ponieważ gniazdo może być dostępne poza twoją aplikacją, po prostu musisz zrobić, co możesz, aby napisać testy jednostkowe wokół złącza i upewnić się, że obsługuje on wszystkie wyjątkowe warunki. Wspomniałeś o błędach "adres jest już w użyciu", więc chciałbym się upewnić, że mój konektor nie umrze tylko z powodu tego stanu. Zrobiłbym test jednostkowy, by stworzyć ten warunek i upewnić się, że go złapie. – Dave

Odpowiedz

4

Napisałem podobną warstwę abstrakcji, chociaż w C/C++, i miałem okazję przetestować kod gniazdowy. Nie wiem, czy jest tu coś nieodłącznie związanego z PHP, więc po prostu zaoferuję ogólne porady.

  • Utwórz gniazdo serwera w konfiguracji, zamknij je w oderwaniu. W zależności od tego, czy obsługujesz wielu klientów łączących się z gniazdem serwera, możesz chcieć wykonać tę część w metodzie testowania.
  • Zakładając, że możesz określić port, z którym chcesz się połączyć w swoim kliencie, podłącz gniazdo serwera do portu 0 (port efemeryczny), a następnie użyj go w kodzie klienta. To wyeliminuje problem związany z portem już używanym.
  • Ustaw limity czasu na swoich gniazdach. Jeśli test nie powiedzie się z jakiegoś nieoczekiwanego powodu, nie chcesz, aby zawieszał się na zawsze.
  • Musisz mieć możliwość przeplatania zachowania klient/serwer. Na przykład będziesz chciał przetestować, co się stanie, jeśli serwer zamknie swoją część połączenia w połowie odczytu/zapisu klienta. Asynchroniczne operacje we/wy lub wielowątkowe wykonają zadanie. Nie jestem pewien, co masz do swojej dyspozycji w PHP.
+0

Myślę, że potrzebowałem porady od programisty C, ze względu na sposób obsługi gniazd PHP. Funkcje gniazd w PHP są bardzo podobne do gniazd C (używają nawet tych samych nazw stałych!). Biorąc to pod uwagę, myślę, że wskazałeś mi właściwy kierunek.Wiążąc port 0 i używając 'getsockname', mogę pobrać numer portu, do którego serwer się związał i podłączyć do niego klienta, nie martwiąc się o porty już używane. Powinienem był o tym pomyśleć wcześniej! Dziękuję Ci bardzo! – netcoder

+0

Aha, i dla wielowątkowości i wielu równoczesnych połączeń, nie muszę się o to martwić. Jest inna klasa zajmująca się tym, więc wszystko, czego potrzebuję, to przetestowanie samego gniazda. – netcoder

2

Mam nadzieję, że jestem zrozumienie Twoje pytanie poprawnie ... Jeśli nie, proszę dać mi wiedzieć. Ale to, co zrobiłbym, to kpić z gniazda. To pozwoliłoby ci napisać serię testów jednostkowych, które zapewnią, że twoja metoda wykonuje wszystkie właściwe rzeczy w różnych przypadkach.

Na przykład można napisać test jednostkowy, który powie instancji impulsu gniazda, aby wyrzucił wyjątek "Port niedostępny". W takim przypadku możesz stwierdzić, że twoja metoda wychwyciła wyjątek i zalogowała go z tym samym tekstem, który znajdował się w tym wyjątku.

I jeszcze bardziej istotna kwestia, można napisać test jednostkowy, który powie instancji impulsu gniazda, aby zwrócił prawidłowy strumień bajtów z read(), a następnie można stwierdzić, że twoja metoda działa prawidłowo (s) z tymi bajtami.

Tak naprawdę nie testujesz gniazda. Konfigurujesz gniazdo, aby symulować pewne wystąpienia i testujesz, aby sprawdzić, czy twój kod współpracujący z gniazdem działa prawidłowo.

(Używałem szyderczych frameworków w Javie, C#, Ruby i JavaScript. Nigdy nie pracowałem z PHP, ale założę się, że jest tam kilka dobrych szyderczych frameworków).

EDYCJA: Tak, istnieją pewne szydercze ramy dla PHP. Nie mogę tego polecić, ale oto para, którą udało mi się znaleźć: PHPUnit i LastCraft

+0

Dzięki za odpowiedź. Używam już PHPUnit. Niestety, w przeciwieństwie do Java i C#, które również wiem, gniazda w PHP są bardzo zbliżone do gniazd C/C++. W rzeczywistości PHP używa opakowania dla biblioteki C. Gniazda PHP nie są obiektami, ale są uważane za zasoby (mniej więcej wskaźniki), które bardziej przypominają typ pierwotny, dlatego nie można ich wyśmiewać. Moje klasy są owijkami dla tych funkcji gniazd i muszę się upewnić, że zwracają * false *, * null * lub dane, gdy muszą, bez niepowodzenia z powodu kolizji. Myślę, że @axw może mieć odpowiedź, której potrzebuję. Wielkie dzięki! – netcoder