1. Защо пишем тестове? 2. Как да се научим? 3. Unit vs. Integration тестове 4. Mocks 5. Test-Driven Development 6. Често срещани проблеми План Saturday, August 11, 12
1. Защо пишем тестове? 2. Как да се научим? 3. Unit vs. Integration тестове 4. Mocks 5. Test-Driven Development 6. Често срещани проблеми План Saturday, August 11, 12
1. Защо пишем тестове? 2. Как да се научим? 3. Unit vs. Integration тестове 4. Mocks 5. Test-Driven Development 6. Често срещани проблеми План Saturday, August 11, 12
1. Защо пишем тестове? 2. Как да се научим? 3. Unit vs. Integration тестове 4. Mocks 5. Test-Driven Development 6. Често срещани проблеми План Saturday, August 11, 12
System Under Test (SUT) друго име за “какво точно тестваме” ще го произнасям “СУТ” всеки тест трябва да има ясна такава помага да категоризираме тестовете Saturday, August 11, 12
Unit Integration Тества един клас Изолиран с mock-ове Бърз Помага за дизайна Тества няколко неща Понякога има stub-ове Бавен Помага за верификацията Saturday, August 11, 12
Feature: Purchasing things In order for us to make money the user should be allowed to easily purchase our products Scenario: Purchases for more than 2500 should offer 20% Given the following products: | Name | Price | | MacBook Pro | 2000 | | ThinkPad | 1000 | When I add 1 "MacBook Pro" to my basket And I add 1 "ThinkPad" to my basket Then the final price should be 2600 Integration Saturday, August 11, 12
Функционалност: Купуване на продукти За да печелим пари потребителят трябва да може лесно да пазарува продукти Сценарий: Поръчките за повече от 2000 трябва да имат 20% отстъпка Дадено че има следните три продукта: | Име | Price | | MacBook Air | 2000 | | ThinkPad | 1000 | Когато добавя 1 "MacBook Air" в кошницата си И добавя 2 "ThinkPad" в кошницата си То цената трябва да е 2600 Integration Saturday, August 11, 12
describe RegistrationsController do describe "PUT update" do context "when valid" do let(:registration) { double } before do Registration.stub :new => registration registration.stub :create => true end it "constructs a Registration with params[:registration]" do Registration.should_receive(:new).with('registration data') post :create, registration: 'registration data' end it "creates a registration" do registration.should_receive(:create) post :create end end end end Unit Saturday, August 11, 12
1. Защо пишем тестове? 2. Как да се научим? 3. Unit vs. Integration тестове 4. Mocks 5. Test-Driven Development 6. Често срещани проблеми План Saturday, August 11, 12
• Този метод трябва да се извика с тези параметри • Този метод не трябва да се извиква Тестовете с mock-ове често поставят очаквания като: Saturday, August 11, 12
class RegistrationsController < ApplicationController def create @registration = Registration.new params[:registration] if @registration.create redirect_to root_path else render :action => :new end end end Saturday, August 11, 12
describe RegistrationsController do describe "PUT update" do context "when valid" do let(:registration) { double } before do Registration.stub :new => registration registration.stub :create => true end it "constructs a Registration with params[:registration]" do Registration.should_receive(:new).with('registration data') post :create, registration: 'registration data' end it "creates a registration" do registration.should_receive(:create) post :create end end end end Saturday, August 11, 12
1. Защо пишем тестове? 2. Как да се научим? 3. Unit vs. Integration тестове 4. Mocks 5. Test-Driven Development 6. Често срещани проблеми План Saturday, August 11, 12
Добавяте тест 1 ...за несъществуващ код Пишете код 2 ...колкото тестът да мине Правите подобрения 3 ...докато премахнете повторенията Saturday, August 11, 12
Добавяте тест 1 ...за несъществуващ код Пишете код 2 ...колкото тестът да мине Правите подобрения 3 ...докато премахнете повторенията Saturday, August 11, 12
Добавяте тест 1 ...за несъществуващ код Пишете код 2 ...колкото тестът да мине Правите подобрения 3 ...докато премахнете повторенията • Тествате кода, който бихте искали да имате • Няма да се компилира (липсващи методи/класове) • Пускате го и гледате как се проваля • Имате червен тест проверяващ функционалността Saturday, August 11, 12
Добавяте тест 1 ...за несъществуващ код Пишете код 2 ...колкото тестът да мине Правите подобрения 3 ...докато премахнете повторенията • Добавяте достатъчно код за да мине теста • Нито ред повече • Най-простото решение, което ви хрумва • Имате работещ код и зелен тест, който го потвърждава Saturday, August 11, 12
Добавяте тест 1 ...за несъществуващ код Пишете код 2 ...колкото тестът да мине Правите подобрения 3 ...докато премахнете повторенията • Не добавяте функционалност • Подобрявате кода/дизайна • Премахвате повторенията • На всяка стъпка пускате теста Saturday, August 11, 12
1 2 3 Кодът, който искате да имате describe "Message" do it "should support initialization" do message = Message.new('[email protected]', '[email protected]', 'Hi!') message.from.should == '[email protected]' message.to.should == '[email protected]' message.title.should == 'Hi!' end end F 1) NameError in 'Message should support initialization' uninitialized constant Message /work/message/spec/message_spec.rb:5: Finished in 0.009336 seconds 1 example, 1 failure Saturday, August 11, 12
1 2 3 Най-простата имплементация class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end end . Finished in 0.009999 seconds 1 example, 0 failures Saturday, August 11, 12
1 2 3 Пас class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end end Всичко изглежда ок, няма нужда от рефакториране Saturday, August 11, 12
1 2 3 Прост регулярен израз class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end def valid? @from =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end end .. Finished in 0.011689 seconds 2 examples, 0 failures Saturday, August 11, 12
1 2 3 Отново пас class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end def valid? @from =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end end Все още всичко е ОК Saturday, August 11, 12
1 2 3 Най-простата имплементация class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end def valid? @from =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ and @to =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end end ... Finished in 0.010058 seconds 3 examples, 0 failures Saturday, August 11, 12
class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end def valid? @from =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ and @to =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end end 1 2 3 Повторение Saturday, August 11, 12
class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end def valid? @from =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ and @to =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end private def email_valid?(address) address =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end end 1 2 3 Малки стъпки ... Finished in 0.010158 seconds 3 examples, 0 failures Saturday, August 11, 12
class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end def valid? email_valid?(@from) and @to =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end private def email_valid?(address) address =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end end 1 2 3 Ама наистина малки стъпки ... Finished in 0.010001 seconds 3 examples, 0 failures Saturday, August 11, 12
class Message attr_reader :from, :to, :title def initialize(from, to, title) @from = from @to = to @title = title end def valid? email_valid?(@from) and email_valid?(@to) end private def email_valid?(address) address =~ /^[a-z][email protected][a-z]+(\.[a-z]+)+$/ end end 1 2 3 Готово ... Finished in 0.009903 seconds 3 examples, 0 failures Saturday, August 11, 12
Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? — Brian Kenighan Saturday, August 11, 12
1. Защо пишем тестове? 2. Как да се научим? 3. Unit vs. Integration тестове 4. Mocks 5. Test-Driven Development 6. Често срещани проблеми План Saturday, August 11, 12