22. Тестване

22. Тестване

22. Тестване

12 януари 2015

Днес

Пета задача

Кратка история

Преди години се занимавах с електроника като хоби.

Нещата, които правех, обикновено изглеждаха така:

Мотивация

Хвърчащият монтаж - плюсове

Хвърчащият монтаж - проблеми

Продукт

Хардуерът в "хвърчащ монтаж" не е завършен продукт.

Legacy код

кошмарът на всеки програмист

Какво е legacy код?

Код без тестове = legacy код

Лош опит

Аз съм допринесъл много за света с код тип "хвърчащ монтаж".

Достигнах до някои изводи по трудния начин.

Завършен продукт = функционалност + тестове

Едва напоследък започнах да виждам софтуера като завършен продукт, с кутия и пазарен вид, когато идва с пълен пакет автоматизирани тестове.

Няма лесен път към просветлението

To test or not to test?

Едно е сигурно - без тестове не може.

Затова затягайте коланите и поемайте по пътя.

In testing I trust!

Терминология

Unit тестове

Интеграционни тестове

xUnit

xUnit is the collective name for several unit testing frameworks that derive their structure and functionality from Smalltalk's SUnit. SUnit, designed by Kent Beck in 1998, was written in a highly-structured object-oriented style.

Assertion

An assertion is a function or macro that verifies the behavior (or the state) of the unit under test. Usually an assertion expresses a logical condition that is true for results expected in a correctly running system under test (SUT). Failure of an assertion typically throws an exception, aborting the execution of the current test.

Test Fixtures

A test fixture (also known as a test context) is the set of preconditions or state needed to run a test. The developer should set up a known good state before the tests, and return to the original state after the tests.

Test case

setup/teardown

Test Suite

A test suite is a set of tests that all share the same fixture. The order of the tests shouldn't matter.

Test Runner

Test Doubles

Общи принципи

Скорост

TDD

test-driven development

Continuous Integration

Метрики

Тестване в Ruby

Test::Unit

Test::Unit - assertions

Test::Unit - пример

require 'test/unit'

class TC_MyTest < Test::Unit::TestCase
  # def setup
  # end

  # def teardown
  # end

  def test_fail
    assert(false, 'Assertion was false.')
  end
end

RSpec

RSpec - пример

RSpec.describe Account do
  it "has a balance of zero when first created" do
    expect(Account.new.balance).to eq(Money.new(0))
  end
end

RSpec - повече информация

Minitest

Компоненти на Minitest

Minitest::Unit

class TestMeme < Minitest::Test
  def setup
    @meme = Meme.new
  end

  def test_that_kitty_can_eat
    assert_equal "OHAI!", @meme.i_can_has_cheezburger?
  end

  def test_that_it_will_not_blend
    refute_match /^no/i, @meme.will_it_blend?
  end

  def test_that_will_be_skipped
    skip "test this later"
  end
end

Minitest::Spec

describe Meme do
  before do
    @meme = Meme.new
  end

  describe "when asked about cheeseburgers" do
    it "must respond positively" do
      @meme.i_can_has_cheezburger?.must_equal "OHAI!"
    end
  end

  describe "when asked about blending possibilities" do
    it "won't say no" do
      @meme.will_it_blend?.wont_match /^no/i
    end
  end
end

Генериране на тестови данни

SimpleCov

Тестване на GUI

Тестване на CLI

Тестване на API-клиенти

Тестване на уеб

Rack::Test

Rack::Test is a small, simple testing API for Rack apps. It can be used on its own or as a reusable starting point for Web frameworks and testing libraries to build on.

Rack::Test - пример

require "rack/test"

class HomepageTest < Test::Unit::TestCase
  include Rack::Test::Methods

  def test_redirect_logged_in_users_to_dashboard
    authorize "bryan", "secret"
    get "/"
    follow_redirect!

    assert_equal "http://example.org/redirected", last_request.url
    assert last_response.ok?
  end
end

Capybara

https://github.com/jnicklas/capybara

Capybara - пример

describe "the signin process" do
  before :each do
    User.make(:email => 'user@example.com', :password => 'password')
  end

  it "signs me in" do
    visit '/sessions/new'
    within("#session") do
      fill_in 'Email', :with => 'user@example.com'
      fill_in 'Password', :with => 'password'
    end
    click_button 'Sign in'
    expect(page).to have_content 'Success'
  end
end

Selenium

PhantomJS

phantomjs.org

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

PhantomJS - пример

просто нещо готино

console.log('Loading a web page');
var page = require('webpage').create();
var url = 'http://www.phantomjs.org/';
page.open(url, function (status) {
  //Page is loaded!
  phantom.exit();
});

Cucumber

Making BDD fun

Gherkin

Feature: Search courses
  Courses should be searchable by topic
  Search results should provide the course code

  Scenario: Search by topic
    Given there are 240 courses which do not have the topic "biology"
    And there are 2 courses, A001 and B205, that each have "biology" as one of the topics
    When I search for "biology"
    Then I should see the following courses:
      | Course code |
      | A001        |
      | B205        | 

Пример с Gherkin и Cucumber

Въпроси