4 kwietnia 2017

Zasada Kolejności Przekształceń 101

Niestety nic mi to nie da, że wszystkie testy przechodzą, bo funkcjonalność jest nadal w lesie. Ponieważ wszystkie testy przechodzą, musimy przestać pisać kod produkcyjny i zająć się kodem testowym. Muszę zrobić, że test sprawdzający możliwość dodania reklamy do mediów spełnia zasadę literki S - Self Validating - czyli samo sprawdzający się z reguły F.I.R.S.T. dla pisania testów.
Test ten nie posiada na razie żadnej asercji:


def test_if_it_possible_to_add_advertising                                                              

  @media.add_advertising(@it_people.telephone_number);                                                 
                                                                                                       
end 

Dodaję asercje czy kolekcja, która zawiera numery telefonów nie jest nullem i jest wypełniona czymś.

Poprzedni odcinek: TU

Dopisuję:

assert_not_nil(@media.ads); 

Odpalam rake i mam na razie błąd kompilacji:

Error: test_if_it_possible_to_add_advertising(ActorsTestClass): NoMethodError:
undefined method `ads' for 
#<Media:0x007f28a02a55d8>                                                                                 
/home/coola/dsp2017/xp-simulator/test/actors_tests.rb:27:in `test_if_it_possible_to_add_advertising'      
     24:   def test_if_it_possible_to_add_advertising                                                     
     25:                                                                                                  
     26:      @media.add_advertising(@it_people.telephone_number);                                        
  => 27:      assert_not_nil(@media.ads);                                                                 
     28:   end                                                                                            
     29:                                                                                                  
     30: 

Wracam więc do kodu produkcyjnego i dodaję zmienną ads:

class Media                                                                                               
                                                                                                          
  attr_accessor :ads                                                                                      
                                                                                                          
  def add_advertising telephone_number                                                                    
                                                                                                          
  end                                                                                                     
                                                                                                          
end 

Odpalam rake i mam tym razem błąd czasu wykonania:

==========================================================================================================
                                                                                                          
Failure: <nil> expected to not be nil.                                                                    
/home/coola/dsp2017/xp-simulator/test/actors_tests.rb:27:in `test_if_it_possible_to_add_advertising'      
                                                                                                          
     24:   def test_if_it_possible_to_add_advertising                                                     
     25:                                                                                                  
     26:      @media.add_advertising(@it_people.telephone_number);                                        
  => 27:      assert_not_nil(@media.ads);                                                                 
     28:   end                                                                                            
     30:                                                                                                  
                                                                                                          
==========================================================================================================
..

Oczekuję, że ads będzie czymś, ale na razie jest niczym. Wracam więc do kodu produkcyjnego.

W klasie Media tworzę konstruktor (w którym kod będzie się odpalał za każdym stworzeniem nowego obiektu przez Media.new) w którym zmienna ads będzie stawała się tablicą obiektów:


def initialize                                                                                          
  @ads = Array.new                                                                                      
end

Odpalam rake i testy przechodzą. Liczba asercji w systemie sukcesywnie się zwiększa.

3 tests, 5 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications---------------------
100% passed    

To dobry znak :)
Chociaż dążenie do jak największego pokrycia kodu (od 80% do 100%) jest moim zdaniem pogonią za wiatrem, to fakt, że mój system spełnia moje założenia, napawa optymizmem.

Nie mogę więcej pisać kodu produkcyjnego - wracam do kodu testowego.

Dodaję sprawdzenie, czy po wywołaniu metody dodawania reklamy - tablica ads zawiera jakiś element.


assert_true @media.ads.any?

Użyłem tu innej składni - usunąłem nawiasy i średnik na końcu, a i tak działa. Bardziej to przypomina język angielski. Fajne :)

Tymczasem wbijam rake i testy nie przechodzą. Spodziewają się wartości true, a dostają false.

coola@sv26 [/home/coola/dsp2017/xp-simulator]# rake                                                       
/usr/share/ruby-2.3.1/bin/ruby ./test/all_tests.rb                                                        
                                                                                                          
Startedsuite ./test/all_tests                                                                             
F                                                                                                         
                                                                                                          
Failure:==================================================================================================
  <true> expected but was                                                                                 
  <false>                                                                                                 
                                                                                                          
/home/coola/dsp2017/xp-simulator/test/actors_tests.rb:28:in `test_if_it_possible_to_add_advertising'      
     25:                                                                                                  
                                                                                                          
     27:      assert_not_nil(@media.ads);people.telephone_number);                                        
  => 28:      assert_true @media.ads.any?                                                                 
     29:   end                                                                                            
     30:                                                                                                  
     31:                                                                                                  
==========================================================================================================


A więc lecę do kodu produkcyjnego:

def add_advertising telephone_number                                                                    
  @ads.push "coś fajnego"                                                                               
end 

Dodaję kod, który spełnia założenia aktualnych testów. Dodaje string do tablicy ads.  Testy przechodzą.
Dlaczego od razu nie wrzucam do tablicy zmiennej wejściowej telephone_number ?
Wymusza to na mnie dyscyplina TDD i coś co nazywa się po angielsku Transformation Priority Premise. Zasada Kolejności Przekształceń wymyślona przez Wujka Boba chroni przed zaplątaniem się w niepotrzebną złożoność. Każe tworzyć testowany kod produkcyjny przy użyciu listy kolejnych przekształceń tak, aby nie pogubić się po drodze. Więc najpierw przekształcenie {nil -> stała} W tym przypadku stałą jest string "coś fajnego", a potem po napisaniu odpowiedniego testu ewentualnie przekształcenie {stała -> skalar} gdzie skalar to zmienna. Ale nie uprzedzajmy faktów. Grzecznie wracam do testów:

Zmieniłem metodę testową tak:

1
2
3
4
5
6
7
8
def test_if_it_possible_to_add_advertising                                                              
                                                                                                          
     @media.add_advertising("5 55 555");                                                                  
     assert_not_nil(@media.ads);                                                                          
     assert_true @media.ads.any?                                                                          
     assert_equal "5 55 555", @media.ads.first                                                            
                                                                                                          
  end

W linii 3 jest wysłanie konkretnego numeru jako reklamy.
W linii 6 sprawdzam czy pierwszy (i na razie jedyny) element tablicy jest tym numerem.

Efekt rake'a jest taki:

Failure: test_if_it_possible_to_add_advertising(ActorsTestClass)
/home/coola/dsp2017/xp-simulator/test/actors_tests.rb:29:in `test_if_it_possible_to_add_advertising'
     26:      @media.add_advertising("5 55 555");
     27:      assert_not_nil(@media.ads);
     28:      assert_true @media.ads.any?
  => 29:      assert_equal "5 55 555", @media.ads.first
     30: 
     31:   end  
     32: 
<"5 55 555"> expected but was
<"coś fajnego">
==========================================================================================================
..

Test nie przechodzi - mogę powrócić do kodu produkcyjnego:


def add_advertising telephone_number                                                                    
    @ads.push telephone_number                                                                            
  end

Obiecałem, że będę wrzucał zmienną i dotrzymałem słowa :)

Testy przechodzą. Numery telefonów się dodają, świat jest uratowany. Można założyć kapcie, usiąść w fotelu i obejrzeć kolejny odcinek Ojca Mateusza.



Commit tego odcinka TU




Brak komentarzy:

Prześlij komentarz

Podstawy Programowania Funkcyjnego Epizod 3

Czy wszystkie Zasady Się Zmieniają? Kiedy tylko zaczynamy używać nowego paradygmatu , porównujemy z nim na...