Test Driven Development
Павел Калашников, SimbirSoft
TL;DR
too long; didn't read
Интеграционные тесты
TDD-обещания
TDD-разочарование
TDD нужен НЕ всегда
Применять или не применять TDD зависит от:
Критерии использования TDD
Описанная структура интерфейсов
Многие тестовые фреймворки поддерживают возможность создания схемы, которая будет актуальна для всех интерфейсов
it "returns valid json matching the candidate types schema" do� get candidates_path, :params => {}, :headers => headers�� expect(response).to match_response_schema("candidates", :strict => true)�end
Один подход к реализации интерфейсов
def show� candidate = Candidate.find(params[:id])�� render(� :json => candidate,� :serializer => CandidateSerializer,� :status => :ok� )�end
Один подход к реализации интерфейсов
def show� user = User.find(params[:id])�� render(� :json => user,� :serializer => UserSerializer,� :status => :ok� )�end
В задаче описана реализация
Критерии
TDD & QA
Методология предполагает, что тесты пишут программисты
Когда TDD не нужен
Задачи без должной проработки
Простой пример:
форма регистрации
Сложные вычисления
Сложные вычисления
-> Сложно предсказать результат
-> Сложно написать тест до реализации
-> Много времени на написание теста
Простой пример:
BI
Безопасность
Обеспечение безопасности сегодня требует участия человека
-> Автоматическое тестирование не очень полезно
-> Тесты до реализации ещё менее полезно
TDD не нужен!
Copy Paste Driven Development + TDD
Условия: описанные интерфейсы + описанные принципы реализации интерфейсов
Порядок действий:
RSpec or Minitest + FactoryGirl + webdriver
Фреймворки для интеграционного тестирования с декларативно-императивным синтаксисоМ
RSpec
it "returns a candidate with the correct ID" do
candidate = create :candidate� get candidate_path candidate�� expect(response.body).to include_json(� "data" => {� "id" => candidate.id.to_s,� "type" => "candidates"� }� )
end
RSpec
it "returns a user with the correct ID" do
user = create :user� get user_path user�� expect(response.body).to include_json(� "data" => {� "id" => user.id.to_s,� "type" => "users"� }� )
end
RSpec
[ :user, :candidate ] do |model_name|
it "returns a #{model_name} with the correct ID" do
object = create model_name� get send "#{model_name}_path", object�� expect(response.body).to include_json(� "data" => {� "id" => object.id.to_s,� "type" => model_name.pluralize(:en)� }� )
end
end
RSpec + Capybara
scenario 'Create new open opportunity and add teachers to it' do
visit opportunities_path
click_on "New opportunity"
fill_in "Name", with: "New opportunity"
fill_in "Amount in $", with: 100
click_on 'Create Opportunity'
fill_in "opportunity_teacher[email]", with: "test@example.com"
click_on "Add teacher"
expect(page).to have_content("test@example.com")
end