Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Test Driven Development
Forum PHP.pl > Forum > PHP > Object-oriented programming
NoiseMc
Chcialbym poznac Wasze zdanie dotyczące Unit Testów.
Osobiście zabieram się do tego od jakiegoś czasu i trudno mi jest to ugryźc. Znam API SimpleTest ale problem leży w tym, że nie wiem co i jak testowac, szczególnie klasy odpowiedzialne za zapis/odczyt danych ... co porównywac i z czym? Mock Objects ... kolejny temat zagadka.

Docelowo chciałbym dojśc do takiego poziomu aly każdy build aplikacji był zautomatyzowany z testami znaczy:
1. Export z SVN
2. Odpal testy
3. Jezeli wszytko ok to przekopiuj odpowiednie pliki do odpowiednich katalogow, poustawiaj prawa dostepu i zalinkuj katalog aplikacji do document_root serwera.

Piszcie co testujecie i jak ... przykladu kodu mile widziane smile.gif
sobstel
Cytat(NoiseMc @ 1.12.2007, 21:36:46 ) *
Docelowo chciałbym dojśc do takiego poziomu aly każdy build aplikacji był zautomatyzowany z testami znaczy:
1. Export z SVN
2. Odpal testy
3. Jezeli wszytko ok to przekopiuj odpowiednie pliki do odpowiednich katalogow, poustawiaj prawa dostepu i zalinkuj katalog aplikacji do document_root serwera.


w tym celu może przydać się Phing
NoiseMc
Phing oczywiscie sie przyda ale jak juz opanuje testowanie winksmiley.jpg
splatch
Ja zasadniczo testowałem z użyciem testów jednostkowych klasy pomocnicze - jakieś utile, których działanie w prosty sposób można zweryfikować. Nigdy nie angażowałem się w testowanie kontrolerów i logiki w nich zawartych, aczkolwiek temat wydaje się ciekawy. Czy jest ktoś na forum, kto czymś takim się zajmował?
NuLL
To zalezy od sytucji smile.gif

Kiedy sie koduje samemu UT ( UnitTest ) 'y to raczej marnowanie czasu - ale to moja opinia. Prowadze sam firme, sam koduje, znam bez manuala parametry metod w swoim framework'u, podobnie jak to co zwracaja. A to sa wlasnie rzeczy ktore sie testuje. Tesy to swietne narzedzie do pracy grupowej - ktos cos zmnienia w metodzie, ale ona dalej musi zwracac to samo, a na taki i taki argument musi sie zachowac tak samo smile.gif Dzieki temu zachowujemy spojnosc softu i nie musimy sie bac, o to ze nasz cudowny software nie bedzie mial dziwnych bugow wynikajacych z dupnego kodu. Z drugiej strony dobry team i tak przezyje bez testow smile.gif

A zamiast SimpleTest lepiej usiasc do PHP_Unita - ma zdecydowanie wieksze spektrum zastosowan smile.gif
Sedziwoj
@NuLL
Albo ja Ciebie nie do końca rozumiem, albo się z Tobą nie zgadzam.
Testy nie tylko sprawdzają co przyjmują i co zwracają, ale czy zwracają to co powinny. Prosta rzecz spr. e-mail możesz dać różne ciągi aby sprawdziło czy to poprawny adres, a zwracać ma odpowiednio prawdę lub fałsz. Co prawda nie widzi mi się aby testować wszystko i pisać jak extreme programming zalecają zaczynając od testów. Bo jak przechodzi testy oznacza, że dany fragment kodu działa prawidłowo.
Co prawda ja do tej pory korzystałem z SimpleTest, ale też nie za dużo, więc nie wypowiem co daje więcej PHP Unit, ale podejście jest to samo. Jest też wbudowane metody testowe, używane przy testowaniu funkcji w PHP, ale one są dość, moim zdaniem, nieporęczne.
splatch
Z tego co obserwowałem PHP Unit w wersji 3 rozwija się dosyć prężnie. Simple Test miał bardzo duży przestój między wersjami:
  1. 2005-05-30 Simple Test 1.0
  2. 2007-07-16 Simple Test 1.0.1 beta2

Przyznacie, że to przepaść czasowa i po tych 2 latach przerwy powinna wychodzić dwójka a nie patch do jedynki. PHP Unit 3 wykorzystuje eZ do testowania eZ components przez co Sebastian Bergman dosyć często produkuje nowe wersje.

Swoją drogą, ciekaw jestem czy kiedyś pojawi się port Test NG w PHP.
Sedziwoj
Tak czytam, w końcu trzeba się douczać, i nie mogę dojść jednej rzeczy.
Czy mając kod:
  1. <?php
  2. class JakiesOperacje {
  3.  protected $objCos;
  4.  public function __construct(){
  5. $this->objCos = new Cos();
  6.  }
  7.  public function zrobTo( $str ){
  8. return $this->objCos->wykonaj( $str );
  9.  }
  10. }
  11. ?>

Jest możliwość podmienienia klasy Cos? Czy muszę modyfikować konstruktor, aby móc go zastąpić spreparowanym obiektem?
splatch
Cytat(Sedziwoj @ 3.12.2007, 20:01:54 ) *
Tak czytam, w końcu trzeba się douczać, i nie mogę dojść jednej rzeczy.
Czy mając kod:
  1. <?php
  2. class JakiesOperacje {
  3.  protected $objCos;
  4.  public function __construct(){
  5. $this->objCos = new Cos();
  6.  }
  7.  public function zrobTo( $str ){
  8. return $this->objCos->wykonaj( $str );
  9.  }
  10. }
  11. ?>

Jest możliwość podmienienia klasy Cos? Czy muszę modyfikować konstruktor, aby móc go zastąpić spreparowanym obiektem?


W najprostszym wypadku można dopisać:
  1. <?php
  2. class ExtJakiesOperacje extends JakiesOperacje {
  3. public function __construct(Cos $myImpl){
  4. parent::__construct();
  5.  
  6. $this->objCos = $myImpl;
  7. }
  8. }
  9. ?>


Fakt, że jest to troszkę na okrętkę, ale sam w ten sposób kiedyś testowałem część kodu, do którego normalnie nie mogłem się dostać. Można próbować podmienić konstruktor via mocki, chociaż wówczas może pojawić się problem z inicjowaniem pola. W Simple Test mamy do dyspozycji partial mock objects.
Sedziwoj
Cytat(splatch @ 3.12.2007, 13:07:23 ) *
Swoją drogą, ciekaw jestem czy kiedyś pojawi się port Test NG w PHP.

http://www.phpunit.de/wiki/Features
Rzuć okiem na drugi punkt ;]

Co do częściowej podmiany, to jest pewien sposób, chyba nawet bardziej mi przypada do gustu, choć pewnie też nie zawsze można tak zrobić :|
Przydało by się dynamiczne zmienianie klas na podstawie których powstają obiekty... ale słyszałem o dynamicznej podmianie w obiekcie, ale dla klas coś mi się nie wydaje, ale może jednak?
NoiseMc
Znalazlem cos ciekawego, przyklad testowania kontrolerow ZF:
http://www.alexatnet.com/node/12

Teraz mam pare pytan dotyczacych testowania warstwy modelu.
Zalozmy, ze mamy klasy, ktore nazwe umownie ProductDO i ProductDAO. ProductDO nie musi byc testowana bo jest tylko obiektem przechowywujacym dane. ProductDAO ma nastepujace metody:
  1. <?php
  2. public function getAll ()
  3. {
  4. /* Pobieranie danych i tworzenie listy obiektow ProductDO */
  5. return $productList;
  6. }
  7.  
  8. public function getByID ($id)
  9. {
  10. /* Zwraca jeden obiekt ProductDO */
  11. return $product;
  12. }
  13.  
  14. public function save (ProductDO $product)
  15. {
  16. /* Zapisuje obiekt */
  17. }
  18. ?>


Jak to teraz przetestowac?

W przypadku getByID() myslalem o sprawdzaniu czy zwraca obiekt typu ProductDO czyli:
  1. <?php
  2. public function testGetByID()
  3. {
  4. $this->assertTrue ($this->productDao->getByID (1) instanceof ProductDO);
  5. }
  6. ?>


ale co jezeli nie mam w bazie zadnych danych .... a moze zamiast testowac w ten sposob powinienem najpierw dodac obiekt do bazy co zwroci mi jego id (last_insert_id), a potem sprawdzic czy getByID zwroci mi obiekt klasy ProductDO.
Sedziwoj
Cytat(NoiseMc @ 12.12.2007, 19:07:41 ) *
Znalazlem cos ciekawego, przyklad testowania kontrolerow ZF:
http://www.alexatnet.com/node/12

Taki sobie artykuł, testuje więcej niż jedną rzecz na raz, a zgodnie z założeniami testy powinny testować jedna małą rzecz. A tu mamy zależności od kontrolerów, bazy danych itd., że taki test się nie powiedzie nie znaczy, że nawalił kod który miał być testowany.

Co do nie testowania ProductDO to się mylisz, ponieważ obiekt powinien przyjmować tylko to co ma i zracać jedynie to co ma zwrócić, a że taki test jest prosty (brak zależności) to szybko się napisze.

Co do testowania ProductDAO, pobiera skądś dane, ale skąd?
Jak bezpośrednio z bazy to musisz mieć testową bazę i na początku testu ją czyścić (tak jak jest to w przykładzie co podałeś) a potem dodać i odczytywać, to co właśnie dodałeś, więc wiesz co powinno być zwrócone.
Jeśli bierze dane z bazy ale przez inny obiekt to powinieneś użyć Mock Objects, który będzie zwracał spreparowane dane. Aby nie testować obiektu pobierającego dane łącznie z tym, ten pobierający powinien mieć osobne testy.

Ale ja jestem słaby w testowaniu, więc mogę się mylić w pewnych sprawach.

P.S. Nie edytuj postu, tylko dopisuj kolejny...
dr_bonzo
1.
Cytat
Taki sobie artykuł, testuje więcej niż jedną rzecz na raz, a zgodnie z założeniami testy powinny testować jedna małą rzecz. A tu mamy zależności od kontrolerów, bazy danych itd., że taki test się nie powiedzie nie znaczy, że nawalił kod który miał być testowany.

Wlasnie znaczy ze nawalil kod ktory mial byc testowany - bo robiles testy integracyjne, czyli testowales jak to wszystko razem, pelna aplikacja, dziala ze soba.

2. a juz zapomnialem co mialo byc w "2."
Sedziwoj
Cytat(dr_bonzo @ 13.12.2007, 01:22:18 ) *
Wlasnie znaczy ze nawalil kod ktory mial byc testowany - bo robiles testy integracyjne, czyli testowales jak to wszystko razem, pelna aplikacja, dziala ze soba.


Tia, a autor napisał to bo łatwiej.
Testy jednostkowe powinny zaczynać się od dołu, a nie od góry.
A ich założenie jest takie, jak każdy fragment działa jak powinien, to całość też działa dobrze. I też za cel spr. przy modyfikacji czy czegoś nie zwaliłeś, więc każdy część powinna być testowana osobno.
Inaczej taki test nie różni się od "przeklikania" i nie ma sensu większego tylko takie robić.
A problem jest w zapewnieniu izolacji testowanych elementów od ich zależności.
NoiseMc
Wedlug mnie powinno sie testowac wszystko na wszystkie sposoby czyli jednostki od dolu i idac do gory testy integracyjne, jezeli kod nie przeszedl testow integracyjnych to trzeba wrocic do jednostkowych i dopisac tyle ile trzeba zeby wylapac blad u dolu, jezeli kod przechodzi to i to to znaczy ze wszystko jest ok.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.