Tdd and BDD
-
Upload
dmitriy -
Category
Technology
-
view
142 -
download
0
description
Transcript of Tdd and BDD
Тестирование
Alex Slynko UkrGermanEnterprise GmbH
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
TDD
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
TDD
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Что это такое?● Test driven development● Вначале тесты – потом код
Виды тестов
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Виды тестов
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Юнит-тесты
● Интеграционные
● Системные
● Интеграции систем
Юнит-тесты
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Одна часть метода
● К внешним сервисам нет реальных обращений
● Желательно только одна проверка в тесте
● Очень быстро работает
Тестирование без других частей
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Dummy – параметры, которые передаются внутрь, но
не используются в тесте. Пустые объекты
● Stub – объекты, которые отвечают на запросы с
заданным ответом
● Mock = Stub + проверка, что методы будут вызваны
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Юнит-тесты
context "bonus_data" do context “percent” do should "be taken from trader if absent in model" do @bonus_data_hash = { :percent => 2, :amount => 200 } @trader = OpenStruct.new(:cars_data => {:bonus_data => @bonus_data_hash, :federal_state => "Sachsen" }) @available_car = Car.make_unsaved(:trader => @trader) assert_equal @bonus_data_hash[:percent], @available_car.bonus_data.first[:percent] end endend
Юнит-тесты
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Упрощает рефакторинг – видно где падает
● Самодокументация
● Минимизирует зависимости
● Упрощает интеграцию
Интеграционные
● Взаимодействие нескольких систем
● Внешние сервисы могут быть разблокированы
● Медленные
● Может быть несколько проверок
● В случае изменения старой системы могут работать
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Интеграционные
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
context "the Body overview" do setup do @model = Car::Model.make_with_discount({}, :bonus_data => [ base_bonus(50) ]) endshould "show disabled models without link to configure the car" do @model.update_attribute(:enabled, false) visit body_url( @model.brand_slug, @model.line_slug, @model.body_slug ) assert_contain "#{@model.brand_name} #{@model.line_name} #{@model.body_name}" assert_contain I18n.t("show_available_models") assert_have_no_selector "a[href='#{body_models_url( @model.brand_slug, @model.line_slug, @model.body_slug )}']" end
Как TDD работает?
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Как это работает на самом деле?
Продаем TDD
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Работать с TDD?
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Плюсы Минусы
● Легче создавать● Легче рефакторить● Документация● Код больше не
страшно трогать
● Я не тестировщик● Не понятно зачем● Надо поддерживать
еще и тесты● Слишком сложная
система
TDD
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Легко● Интересно
● Сложно● Скучно
Не совсем TDD
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Тесты должны идти в коммите с кодом
● Не весь код должен иметь тесты
● Не совсем помогает
Примеры
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Hotel
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Добавить флажок для гостя, что он ребенок
Autoleasing
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Ежедневно получаем список доступных машин от
компании. Добавить checksum и не обновлять машину,
если ее checksum такой же как был.
should "update car with changes" do AvailableCarsImporter.import car = Car::Available.first car.update_attribute(:trim_level, nil) car.update_attributes({:checksum => 'Changed checksum'}) Car::Available.expects(:save).once AvailableCarsImporter.import assert car.reload.trim_levelend
TDD. Примеры
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Нужны ли эти тесты?
● Помогли ли они нам?
● Пригодятся ли в будущем?
Пример def calculate_leasing_data leasing_info = self.leasing_data options = { :vehicle_id => self.vehicle_id, :ld => leasing_info[:runtime].to_i, :jkm => leasing_info[:mileage].to_i, :sozp => leasing_info[:downpayment_percent].to_d.round, :sfan => self.brand_name } becos = options_data.map {|option| option[:option_code] } if options_data options[:becos] = becos if becos.present? output_data = LeasingDataCalculator.get_leasing_data(options) if output_data and !(output_data == [] or output_data.try(:[], "err").present? or (records = output_data.try(:[], "rec")).blank?) and month_rate = records.try(:[], "FL").try(:[], "mrat") delivery_costs_leasing = records.try(:[], "LP").try(:[], "mrat") || 0.0 LeasingData.create( :rate => month_rate.to_d, :offer_id => self.id, :downpayment_percent => leasing_info[:downpayment_percent].to_d.round, :mileage => leasing_info[:mileage], :downpayment_amount => leasing_info[:downpayment_amount].to_d, :runtime => leasing_info[:runtime], :delivery_costs_leasing => delivery_costs_leasing, :additional_info => records.to_json ) else error_message = I18n.t("leasing_data_not_saved", :leasing_offer_id => self.id) Airbrake.notify(:error_class => "CreateLeasingDataError", :error_message => error_message, :parameters => options) end end
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Примерif output_data and !(output_data == [] or output_data.try(:[], "err").present? or (records = output_data.try(:[], "rec")).blank?) and month_rate = records.try(:[], "FL").try(:[], "mrat") delivery_costs_leasing = records.try(:[], "LP").try(:[], "mrat") || 0.0... else error_message = I18n.t("leasing_data_not_saved", :leasing_offer_id => self.id) Airbrake.notify(:error_class => "CreateLeasingDataError", :error_message => error_message, :parameters => options) end end
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Пример.. output_data = LeasingDataCalculator.get_leasing_data(options)
…
Class LeasingDataCalculator def self.get_leasing_data(options) return {} if option[:some].blank?
#И еще несколько подобных проверок options = prepare_options(options) WebServices.get_leasing_data(options) endend
Пример
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
output_data = { "rec" => { "FL" => { "mrat" => "123.45" }, "LP" => { "mrat" => "234.56" } } }WebServices.stubs(:get_leasing_data).returns(output_data)assert_difference("LeasingData.count") { @offer.calculate_leasing_data }leasing_data = LeasingData.lastassert_equal @offer, leasing_data.offerassert_equal 123.45, leasing_data.rateassert_equal 20, leasing_data.downpayment_percentassert_equal 10000, leasing_data.mileageassert_equal 1234, leasing_data.downpayment_amountassert_equal 12, leasing_data.runtimeassert_equal 234.56, leasing_data.delivery_costs_leasingassert_equal output_data["rec"].to_json, leasing_data.additional_info
Пример
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
should "notify airbrake about not updated leasing data" doWebServices.stubs(:get_leasing_data).returns({"err" => "some error"})error_message = I18n.translate("leasing_data_not_saved", :leasing_offer_id => @offer.id)Airbrake.expects(:notify).with(:error_class => "CreateLeasingDataError", :error_message => error_message)@offer.calculate_leasing_dataend
Пример
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
def calculate_leasing_data output_data = LeasingDataCalculator.get_leasing_data(self) if output_data[:error].blank? LeasingData.create(output_data) else error_message = I18n.t(“create_offer_errors.leasing_data_not_saved", :leasing_offer_id => self.id) Airbrake.notify(:error_class => "CreateLeasingDataError", :error_message => error_message) end end
Продаем дальше
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Позволить работать с TDD?
Плюсы
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Минусы
● Довольные
программисты● Уменьшение
количества регрессий● Проще обновлять
библиотеки
● Больше времени на
задание● Тяжело роверить● Отдельный тестовый
сервер
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Последний доводТесты позволяют писать код не приходя в сознание
Надо думать
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Приемочные тесты
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Требования выполнены
● Не знает ничего о внутренней структуре (черный
ящик)
● Объясняется в терминах заказчика (возможно, даже
заказчиком)
Приемочные● Given Jira Issue with several bugs
● When all that bugs are fixed
● Then Issue is closed
Взято с Хабра ©
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Приемочные● Given Jira Issue with 1 bug
● And I am on issue overview page
● When I fix it
● Then Issue is closed
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
BDD
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Что это такое?● Behaviour driven development
● Вначале приемочные тесты – потом код
Как это работает?
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Позволить работать с BDD?
Плюсы
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Минусы
● Уменьшение количества
регрессий● Можно проверить что
делают● Улучшается понимание
● Еще больше
времени на задание● Отдельный
тестовый сервер
Примеры
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Примеры- В комнате должен быть хотя бы один
дееспособный человек
Given a kid client “John”And an adult client “Jake”Then I can not reserve room for “John”But I can reserve room for “Jake”And I can reserve room for “Jake” and “John”
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Leasing
Given car which is importedAnd I changed itWhen I approved itAnd run import againThen car should be still approvedWhen run import again with different dataThen car should be unapproved
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Как это может не работать?
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Тесты не чиняться
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Неправильные тесты
После работы метода берем результат с которым потом и
сравниваем.
order = Order.build(VAT: 19, discount: 5)
order.items << (line_item = LineItem.build(price: 100.5))
assert 134.595, order.total_amount
● URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Долгие тесты
URL: www.acceptic.com
Software programming servicesand dedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Сохраняет данные в базу данных, когда это не нужно
order = Order.make(VAT: 19, discount: 5)order.items << (line_item = LineItem.make(price: 100.5))assert 133.65, order.total_amount
Сложнотестируемый код
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Взаимодествие одного метода с большим количеством
объектов
public XlsFile GenerateReport() { int period; if (DateTime.Today.DayOfWeek == DayOfWeek.Sunday) { period = 7 } else { period = SomeServiceClient().GetPeriod(); }
…
Код написанный для тестов
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
# app/use_cases/post_comment.rb# Called from the "create" action in a controllerclass PostComment def initialize(user, entry, attributes) @user, @entry, @attributes = user, entry, attributes end
def post @comment = @user.comments.new @comment.assign_attributes(@attributes) @comment.entry = @entry @comment.save!
LanguageDetector.new(@comment).set_language SpamChecker.new(@comment).check_spam CommentMailer.new(@comment).send_mail post_to_twitter if @comment.share_on_twitter? post_to_facebook if @comment.share_on_facebook? @comment end
private def post_to_twitter PostToTwitter.new(@user, @comment).post end
def post_to_facebook PostToFacebook.new(@user, @comment).action(:comment) endend
Взаимозависимые тесты
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
● Изменение конфигурации перед тестом (и не
изменение после)
● Сохранение специального конфига в базе данных
APP_CONFIG[:available_cars][:traders] = { "TRADER_ID" => @trader.id }
Вера во время
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Запись, которая создается позже имеет timestamp
больше
bmw = Car.make(:brand_name => ‘bmw’)audi = Car.make(:brand_name => ‘audi’)
assert _equal [bwm, audi], Car.order(:created_at).all
Порядок
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370
Порядок не обязан сохраняться, если только он не
прописан явно
record1 = Car.make(:brand => ‘Audi’)record2 = Car.make(:brand => ‘Audi’)assert_equal [record1, record2], Car.by_brand(‘Audi’)
Вопросы?
URL: www.acceptic.com
Software programming services andDedicated developers teams
E-mail: [email protected]
Tel.: +1 800 990 4370