31 marca 2017

W ciemność

Ostatnio na naszym kanale Slackowym kolega polecił mi, żebym zmienił bibliotekę do unit testów na nowszą i częściej używaną. Zachęcał mnie do wybrania raczej biblioteki minitest. Rzeczywiście jest to biblioteka bardziej popularna i więcej może. Tylko ja z moją starą biblioteką test-unit nadal spełniam warunek numer 3 z przysięgi programisty:
3. Dostarczyć z każdą wersją aplikacji szybki, pewny i powtarzalny dowód, że każda część kodu działa tak jak powinna.
Jeżeli tak, to po co bić pianę? Jeżeli będę potrzebował większych możliwości w przyszłości rzeczywiście zmienię bibliotekę. Na razie postąpię według reguły KISS (nie komplikuj głuptasku).


Dopiszę kolejne wymaganie do naszej aplikacji. Klienci i Goście z IT mogą zasubskrybować Media. Mogą też wysłać swoją reklamę, która ukaże się cykliczne w medium proponowanym przez Media.

Do mojego pliku z testami dodałem nowy test, w którym oczekuję, że będę mógł dodać reklamę z telefonem do swojej firmy.

def test_if_it_possible_to_add_advertising                                                                                                                                                                                                 
    it_people = ItPeople.new                                                                                                                                                                                                                 
    media = Media.new                                                                                                                                                                                                                        
    media.add_advertising(it_people.telephone_numer);                                                                                                                                           
end

Zgodnie z drugim prawem TDD skoro mam błędy kompilacji ...

NoMethodError: undefined method `category' for #<Media:0x007fd3eefabaa8>

... muszę przerwać pisanie testu i dodaję kod produkcyjny. A więc teraz klasa ItPeople musi wyglądać tak:

class ItPeople

  attr_accessor :telephone_number

end

Przy czym attr_accessor dodaje zmienną do klasy z możliwością jej edycji i odczytu.

A klasa Media przybierze postać:


class Media

  attr_accessor :categories                                                                                                                                                                                                                  
                                                                                                                                                                                                                                             
  def add_advertising telephone_number                                                                                                                                                                                                       
                                                                                                                                                                                                                                             
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
end  

I tu muszę wspomnieć, że po nazwie metody, po spacji dajemy listę parametrów metody. Mogę dać nawiasy, ale nie muszę.

Teraz, ponieważ testy przechodzą przerywam pisanie kodu produkcyjnego. Ponieważ mam leciutką duplikację w testach w deklaracji obiektów zrobię refaktor.

Zamienię to:


require "test-unit"                                                                                                                                                                                                                          
require "./src/Client.rb"                                                                                                                                                                                                                    
require "./src/ItPeople.rb"                                                                                                                                                                                                                  
require "./src/Media.rb"                                                                                                                                                                                                                     
                                                                                                                                                                                                                                             
class FirstSmokeTestClass < Test::Unit::TestCase                                                                                                                                                                                             
                                                                                                                                                                                                                                             
  def test_if_this_test_framework_works                                                                                                                                                                                                      
                                                                                                                                                                                                                                             
    assert_equal(2, 1 + 1)                                                                                                                                                                                                                   
                                                                                                                                                                                                                                             
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
  def test_if_there_are_actors_of_that_tragedy                                                                                                                                                                                               
                                                                                                                                                                                                                                             
    client = Client.new                                                                                                                                                                                                                      
    it_people = ItPeople.new                                                                                                                                                                                                                 
    media = Media.new                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
    assert_not_nil(client);                                                                                                                                                                                                                  
    assert_not_nil(it_people);                                                                                                                                                                                                               
    assert_not_nil(media);                                                                                                                                                                                                                   
                                                                                                                                                                                                                                             
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
  def test_if_it_possible_to_add_advertising                                                                                                                                                                                                 
    it_people = ItPeople.new                                                                                                                                                                                                                 
    media = Media.new                                                                                                                                                                                                                        
    media.add_advertising(it_people.telephone_number);                                                                                                                                                                                       
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                             
end  


W to:


require "test-unit"                                                                                                                                                                                                                          
require "./src/Client.rb"                                                                                                                                                                                                                    
require "./src/ItPeople.rb"                                                                                                                                                                                                                  
require "./src/Media.rb"                                                                                                                                                                                                                     
                                                                                                                                                                                                                                             
class FirstSmokeTestClass < Test::Unit::TestCase                                                                                                                                                                                             
                                                                                                                                                                                                                                             
  def setup                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                             
    @client = Client.new                                                                                                                                                                                                                     
    @it_people = ItPeople.new                                                                                                                                                                                                                
    @media = Media.new                                                                                                                                                                                                                       
                                                                                                                                                                                                                                             
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                             
  def test_if_this_test_framework_works                                                                                                                                                                                                      
                                                                                                                                                                                                                                             
    assert_equal(2, 1 + 1)                                                                                                                                                                                                                   
                                                                                                                                                                                                                                             
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
  def test_if_there_are_actors_of_that_tragedy                                                                                                                                                                                               
                                                                                                                                                                                                                                             
    assert_not_nil(@client);                                                                                                                                                                                                                 
    assert_not_nil(@it_people);                                                                                                                                                                                                              
    assert_not_nil(@media);                                                                                                                                                                                                                  
                                                                                                                                                                                                                                             
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
  def test_if_it_possible_to_add_advertising                                                                                                                                                                                                 
                                                                                                                                                                                                                                             
     @media.add_advertising(@it_people.telephone_number);                                                                                                                                                                                    
                                                                                                                                                                                                                                             
  end                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                             
end    

Dodaję metodę setup, która odpala się za każdym razem, gdy odpala się test.
Dodatkowo zamiast zmiennych lokalnych ustawiam zmienne klasowe, których używam w dwóch ostatnich testach.

Nie podoba mi się jeszcze, że wszystkie testy są w jednym pliku testowym. Przeniosę nowe testy do nowego pliku actors_tests.rb i zaktualizuję Rakefile.

Powinienem chyba utworzyć tak zwane jarzmo testowe:

coola@sv26 [/home/coola/dsp2017/xp-simulator]# touch ./test/all_tests.rb    

Z zawartością:

require 'test/unit/testsuite'                                                                                                                                                                                                                
require './test/smoke_test.rb'                                                                                                                                                                                                               
require './test/actors_tests.rb' 

Odkryłem przypadkiem, że wystarczy odpalić taki plik poleceniem ruby i wszystkie testy wystartują automatycznie.

No dobra, czyli Rakefile powinien teraz wyglądać tak:


task default: %w[test]                                                                                                                                                                                                                       
                                                                                                                                                                                                                                             
task :test do                                                                                                                                                                                                                                
  ruby "./test/all_tests.rb"                                                                                                                                                                                                                 
end 

Dalsze przypadki testowe dopiszę wkrótce.

Link do commita zmian tu: https://github.com/coola/xp-simulator/commit/56d56a37e1c46b571924cf3d640540e6d548cc63

Mam wrażenie, że krzywa wejścia w Ruby jest mimo wszystko stroma, błądzę po omacku, szukam konstrukcji znajomych z innych języków, czując pod skórą, że mimo wszystko warto.

"Zabierz Pan nas stąd, Panie Sulu" Kapitan James T. Kirk



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...