Przejdź do głównej zawartości

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




Komentarze

Popularne posty z tego bloga

Kursy IT na Pluralsight. Dlaczego warto?

Bardzo sobie cenię kursy na Pluralsight. Mam wrażenie, że każdy kurs, który przeszedłem na tej platformie, w dużym stopniu podniósł moje zdolności. Wiem, dostęp do tej platformy nie jest tani, ale w mojej ocenie warty swojej ceny. To nie jest reklama, ale forma entuzjazmu jaki mam do tej formy samodoskonalenia. O to kilka punktów pokazujących ofertę tego serwisu i dlaczego warto skorzystać: Pluralsight to kursy z Javascript, C#, Java, Angular, Python, MySQL i wielu innych technologii i umiejętności. Kursy na Pluralsight w większości mają wyższą jakość niż te, które możemy znaleźć na przykład na YouTube. Są wyselekcjonowane, mają wysoką jakość dźwięku i obrazu. Często wgryzają się głęboko w dany problem daleko poza standardowe „Hello World” danej technologii. Twórcy Pluralsight to często osoby znane ze świata IT i konferencji branżowych, jak: Scott Hanselman, Microsoft John Somnez, SimpleProgrammer.com John Skeet, Google Pluralsight udostępnia funkcjonalność ścieżek – paths....

Bicie piany

Czy słyszałeś o tym gościu, który powiedział, że Object Oriented to przeżytek? No nie. Następny. Co powiedział? Opisał wszystkie obietnice OO, i jak żadna z nich tak naprawdę nigdy nie została spełniona i o tych wszystkich możliwościach OO, które kosztują więcej, niż są warte i że funkcjonalne programowanie jest lepsze i ... Phi. Tak słyszałem już to wcześniej. No, więc OO jest martwe, leży i kwiczy i możemy przejść dalej. Przejść dalej do czego? Co? No do NASTĘPNEJ WIELKIEJ RZECZY oczywiście. Aaaa, do tego. Czy wiesz już co to jest? Nie bałdzo, ale jestem podekscytowany na myśl o mikroserwisach; jaram się Elixirem; i słyszałem, że React jest fantastyczny; i ... Tak, tak. Bicie piany. Dałeś się nabrać na bicie piany. Co? Co masz na myśli. Przecież mamy takie wspaniałe czasy. Tak naprawdę postrzegam te czasy jako depresyjne. Ale dlaczego? Przecież co kilka dni wyskakują nowe wspaniałe technologie! Wspinamy się na coraz wyższe szczyty. Phi. To, co tak napraw...

Podstawy Programowania Funkcyjnego Epizod 1

O czym jest programowanie funkcyjne? Zakładam, że słyszałeś już kiedyś o programowaniu funkcyjnym. No cóż, któż nie słyszał? Wszyscy o tym gadają. Wychodzi dużo nowych języków funkcyjnych takich, jak Scala, F# i Clojure. Ludzie rozmawiają też o starszych językach jak Erlang, Haskell, ML i innych. A więc, o co w tym wszystkim chodzi? Dlaczego programowanie funkcyjne jest Następną Wielką Rzeczą™? I co jest w tym takiego pociągającego? Poniższy tekst jest luźnym tłumaczeniem wpisu bloga Roberta Cecila "Wujka Boba" Martina z dnia 22 grudnia 2012 ze strony: https://blog.cleancoder.com/uncle-bob/2012/12/22/FPBE1-Whats-it-all-about.html Proszę o komentarze, jeżeli ta luźność jest zbyt daleko posunięta. Po pierwsze, prawie na pewno programowanie funkcyjne jest następną wielką rzeczą. Są ku temu dobre, solidne powody i poznamy je w tym artykule. Ale najpierw, aby zrozumieć te powody, musimy poznać, czym programowanie funkcyjne jest....