Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Minitest: voltando ao básico sobre testes

Minitest: voltando ao básico sobre testes

Minitest nasceu como uma alternativa ao test/unit do Ruby 1.8 e se tornou um framework de testes extremamente robusto e ao mesmo tempo simples, e está disponível em qualquer instalação de Ruby hoje em dia, para todos escrevem testes sem muita burocracia.

5a90a67fa1a92e6a4b605cfd8da5e375?s=128

Lucas Mazza

July 23, 2016
Tweet

Transcript

  1. None
  2. Lucas Mazza @lucasmazza http:/ /afterhours.io

  3. https:/ /sp.femug.com https:/ /github.com/braziljs/femug

  4. None
  5. Minitest Voltando ao básico sobre testes

  6. None
  7. https:/ /github.com/seattlerb/minitest

  8. $ gem fetch minitest && gem unpack minitest-*.gem Downloaded minitest-5.9.0

    Unpacked gem: '/private/tmp/minitest-5.9.0' $ cloc minitest-5.9.0/lib 14 text files. 14 unique files. 0 files ignored. github.com/AlDanial/cloc v 1.68 T=0.09 s (159.9 files/s, 38368.5 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- Ruby 14 661 1072 1627 ------------------------------------------------------------------------------- SUM: 14 661 1072 1627 -------------------------------------------------------------------------------
  9. Ruby arroz com feijão

  10. class PostTest < Minitest::Test def test_sets_the_title post = Post.new post.title

    = 'The Post Title' assert_equal 'The Post Title', post.title end def test_publish_publishes_the_post post = Post.new post.publish! assert_predicate post, :published? end end
  11. class PostTest < Minitest::Test def test_sets_the_title post = Post.new post.title

    = 'The Post Title' assert_equal 'The Post Title', post.title end def test_publish_publishes_the_post post = Post.new post.publish! assert_predicate post, :published? end end Caso de teste
  12. class PostTest < Minitest::Test def test_sets_the_title post = Post.new post.title

    = 'The Post Title' assert_equal 'The Post Title', post.title end def test_publish_publishes_the_post post = Post.new post.publish! assert_predicate post, :published? end end Teste Teste Caso de teste
  13. class PostTest < Minitest::Test def test_sets_the_title post = Post.new post.title

    = 'The Post Title' assert_equal 'The Post Title', post.title end def test_publish_publishes_the_post post = Post.new post.publish! assert_predicate post, :published? end end Teste Teste Asserção Asserção Caso de teste
  14. RSpec.describe Post do it '#title= sets the title' do post

    = Post.new post.title = 'The Post Title' expect(post.title).to eq('The Post Title') end it '#publish! publishes the post' do post = Post.new post.publish! expect(post).to be_published end end Teste Teste Asserção Asserção Caso de teste
  15. class PostSpec < RSpec::Core::ExampleGroup set_it_up 'Post', [], RSpec.world.example_groups RSpec::Core::Example.new(self, '#title=

    sets the title', {}, -> (example) { post = Post.new post.title = 'The Post Title' RSpec::Expectations::ExpectationTarget.new(post.title).to( RSpec::Matchers::BuiltIn::Eq.new('The Post Title')) }) RSpec::Core::Example.new(self, 'publish! publishes the post', {}, -> (example) { post = Post.new post.publish! RSpec::Expectations::ExpectationTarget.new(post).to( RSpec::Matchers::BuiltIn::BePredicate.new(:be_published)) }) end RSpec.world.record PostSpec
  16. class PostSpec < RSpec::Core::ExampleGroup set_it_up 'Post', [], RSpec.world.example_groups RSpec::Core::Example.new(self, '#title=

    sets the title', {}, -> (example) { post = Post.new post.title = 'The Post Title' RSpec::Expectations::ExpectationTarget.new(post.title).to( RSpec::Matchers::BuiltIn::Eq.new('The Post Title')) }) RSpec::Core::Example.new(self, 'publish! publishes the post', {}, -> (example) { post = Post.new post.publish! RSpec::Expectations::ExpectationTarget.new(post).to( RSpec::Matchers::BuiltIn::BePredicate.new(:be_published)) }) end RSpec.world.record PostSpec Caso de teste
  17. class PostSpec < RSpec::Core::ExampleGroup set_it_up 'Post', [], RSpec.world.example_groups RSpec::Core::Example.new(self, '#title=

    sets the title', {}, -> (example) { post = Post.new post.title = 'The Post Title' RSpec::Expectations::ExpectationTarget.new(post.title).to( RSpec::Matchers::BuiltIn::Eq.new('The Post Title')) }) RSpec::Core::Example.new(self, 'publish! publishes the post', {}, -> (example) { post = Post.new post.publish! RSpec::Expectations::ExpectationTarget.new(post).to( RSpec::Matchers::BuiltIn::BePredicate.new(:be_published)) }) end RSpec.world.record PostSpec Teste Teste Caso de teste
  18. class PostSpec < RSpec::Core::ExampleGroup set_it_up 'Post', [], RSpec.world.example_groups RSpec::Core::Example.new(self, '#title=

    sets the title', {}, -> (example) { post = Post.new post.title = 'The Post Title' RSpec::Expectations::ExpectationTarget.new(post.title).to( RSpec::Matchers::BuiltIn::Eq.new('The Post Title')) }) RSpec::Core::Example.new(self, 'publish! publishes the post', {}, -> (example) { post = Post.new post.publish! RSpec::Expectations::ExpectationTarget.new(post).to( RSpec::Matchers::BuiltIn::BePredicate.new(:be_published)) }) end RSpec.world.record PostSpec Teste Teste Asserção Asserção Caso de teste
  19. Acompanhamentos

  20. class IntegrationTest < Minitest::Test def setup super DatabaseCleaner.start end def

    teardown super DatabaseCleaner.clean end end hooks
  21. module SerializerTests def setup # ... end def test_serializer_works #

    ... end end Testes compartilhados
  22. class JSONSerializerTest < MiniTest::Test include SerializerTests def serializer JSON end

    end class MarshalSerializerTest < MiniTest::Test include SerializerTests def serializer Marshal end end Testes compartilhados
  23. # activerecord/test/cases/base_test.rb class LintTest < ActiveRecord::TestCase include ActiveModel::Lint::Tests class LintModel

    < ActiveRecord::Base; end def setup @model = LintModel.new end end Testes compartilhados
  24. executando

  25. $ command minitest -bash: minitest: command not found

  26. require 'minitest/autorun' ruby test_file.rb ➕

  27. class Post attr_accessor :title def publish! @published = true end

    def published? @published end end require 'minitest/autorun' class PostTest < Minitest::Test def test_sets_the_title post = Post.new post.title = 'The Post Title' assert_equal 'The Post Title', post.title end def test_publish_publishes_the_post post = Post.new post.publish! assert_predicate post, :published? end end
  28. executando

  29. # active_record_bug.rb require 'bundler/inline' gemfile(true) do source 'https://rubygems.org' gem 'activerecord',

    '5.0.0' gem 'sqlite3' end # ... executando
  30. require 'active_record' require 'minitest/autorun' require 'logger' ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')

    ActiveRecord::Schema.define do create_table :posts, force: true do |t| end end class Post < ActiveRecord::Base end # ... executando
  31. class BugTest < Minitest::Test def test_create_bang post = Post.create! assert_predicate

    post, :persisted? assert_equal 1, post.id end end executando
  32. executando

  33. http:/ /guides.rubyonrails.org/contributing_to_ruby_on_rails.html executando

  34. asserções

  35. assert assert_empty assert_equal assert_in_delta assert_in_epsilon assert_includes assert_instance_of assert_kind_of assert_match assert_nil

    assert_operator assert_output assert_predicate assert_raises assert_respond_to assert_same assert_send assert_silent assert_throws Minitest::Assertions
  36. # lib/minitest/assertions.rb def assert_includes collection, obj, msg = nil msg

    = message(msg) { "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" } assert_respond_to collection, :include? assert collection.include?(obj), msg end Minitest::Assertions
  37. refute refute_empty refute_equal refute_in_delta refute_in_epsilon refute_includes refute_instance_of refute_kind_of refute_match refute_nil

    refute_operator refute_predicate refute_respond_to refute_same Minitest::Assertions
  38. assert post.published? # Expected nil to be truthy. assert_predicate post,

    :published? # Expected #<Post:0x007f8fdc0939b8> to be published?. Minitest::Assertions
  39. # test/support/assertions.rb def refute_file(path, msg = nil) msg = message(msg)

    { "Expected '#{path}' to not exist." } refute File.exist?(path), msg end def assert_file(path, contents = nil, msg = nil) msg = message(msg) { "Expected '#{path}' to exist." } assert File.exist?(path), msg if contents.present? assert_equal contents, File.read(path) end end asserções
  40. plugins

  41. plugins minitest-around minitest-bisect minitest-capybara minitest-debugger minitest-proveit minitest-reporters minitest-utils minitest-matchers ...

  42. fnando/minitest-utils require 'bundler/inline' gemfile(true) do gem 'minitest' gem 'minitest-utils', require:

    false end require 'minitest/autorun' class PluginTest < Minitest::Test def test_that_fails assert_equal 1, 2 end end
  43. fnando/minitest-utils

  44. fnando/minitest-utils

  45. Minitest + Rails

  46. require 'active_support' require 'active_support/test_case' class PostTest < ActiveSupport::TestCase test '#title=

    sets the title' do post = Post.new post.title = 'The Post Title' assert_equal 'The Post Title', post.title end test '#publish! publishes the post' do post = Post.new post.publish! assert_predicate post, :published? end end gem install activesupport
  47. require 'active_support' require 'active_support/test_case' class PostTest < ActiveSupport::TestCase setup :setup_something

    setup { setup_something_else } teardown :teardown_something end gem install activesupport
  48. assert_difference assert_deprecated assert_called assert_called_with assert_no_difference assert_not_deprecated assert_not assert_not_called gem install

    activesupport
  49. Casos de teste ActionController::TestCase ActionDispatch::IntegrationTest ActionMailer::TestCase ActionView::TestCase ActiveJob::TestCase Módulos ActionMailer::TestHelper

    ActiveJob::TestHelper Minitest + Rails
  50. Minitest + Rails

  51. + fixtures + travel_to + rails-controller-testing + ActionDispatch::PerformanceTest + ...

    Minitest + Rails
  52. None
  53. None
  54. mocks & stubs

  55. mocks book = double('book') null_book = double('book').as_null_object book = instance_double('Book',

    pages: 250) allow(book).to receive_messages( title: 'The RSpec Book', pages: 250) invitation = spy('invitation')
  56. mocks require 'minitest/mock' book = Minitest::Mock.new book.expect(:pages, 250) book.expect(:title, 'The

    RSpec Book’) book.expect(:title, 'The RSpec Book’) book.expect(:update, true, [{ title: 'New Title’ }]) assert_mock book
  57. stubs allow(book).to receive_messages( title: 'The RSpec Book', pages: 250) expect(book).to

    receive_messages( title: 'The RSpec Book', pages: 250) allow_any_instance_of(Book).to receive(:update).with(hash_including(title: 'New Title')) { true }
  58. stubs Book.stub(:find, book) do book.stub(:update, true) do # ... end

    end
  59. None
  60. Mocks e stubs não são de graça

  61. (E até que isso é bom)

  62. “…any pain in faking something should be responded to not

    with ever-more-clever test double libraries, but with a redesign of the interaction between the subject and its dependencies.” Justin Searls - Don’t mock what you don’t own https:/ /github.com/testdouble/contributing-tests/wiki/Don't-mock-what-you-don't-own
  63. + API Design - Stubs

  64. + Fake objects - Mocks

  65. + Fake objects - Mocks Mockers without borders https:/ /github.com/testdouble/test-smells/blob/master/smells/unrealistic/mockers-without-borders.js

  66. Escrita de testes

  67. http:/ /blog.plataformatec.com.br/2014/04/improve-your-test-readability-using-the-xunit-structure/

  68. RSpec.describe Post do subject { Post.new } let(:foo) { }

    let(:bar) { } describe '...' do before { } let(:bar) { } context '...' do before { } let(:foo) { } it { } it { } end context '...' do before { } let(:bar) { } it { } it { } it { } end end end
  69. RSpec.describe Post do subject { Post.new } let(:foo) { }

    let(:bar) { } describe '...' do before { } let(:bar) { } context '...' do before { } let(:foo) { } it { } it { } end context '...' do before { } let(:bar) { } it { } it { } it { } end end end
  70. RSpec.describe Post do subject { Post.new } let(:foo) { }

    let(:bar) { } describe '...' do before { } let(:bar) { } context '...' do before { } let(:foo) { } it { } it { } end context '...' do before { } let(:bar) { } it { } it { } it { } end end end
  71. RSpec.describe Post do subject { Post.new } let(:foo) { }

    let(:bar) { } describe '...' do before { } let(:bar) { } context '...' do before { } let(:foo) { } it { } it { } end context '...' do before { } let(:bar) { } it { } it { } it { } end end end
  72. RSpec.describe Post do subject { Post.new } let(:foo) { }

    let(:bar) { } describe '...' do before { } let(:bar) { } context '...' do before { } let(:foo) { } it { } it { } end context '...' do before { } let(:bar) { } it { } it { } it { } end end end (˽°□°҂˽Ɨ ˍ━ˍ
  73. class PostTest < Minitest::Test def test_sets_the_title post = Post.new post.title

    = 'The Post Title' assert_equal 'The Post Title', post.title end end
  74. class TestCase < Minitest::Test def test_name setup exercise verify end

    end
  75. class TestCase < Minitest::Test def test_name verify end end

  76. class TestCase < Minitest::Test def test_name verify end end

  77. class TestCase < Minitest::Test def test_name verify end end ❓❓❓

  78. + Expressividade - DRY

  79. + Isolamento - Dependências

  80. http:/ /xunitpatterns.com/index.html

  81. class PostTest < Minitest::Test def test_sets_the_title post = Post.new post.title

    = 'The Post Title' assert_equal 'The Post Title', post.title end def test_publish_publishes_the_post post = Post.new post.publish! assert_predicate post, :published? end end
  82. QUnit.module('Post tests'); QUnit.test('sets the post title', function(assert) { var post

    = new Post(); post.set('title', 'The Post Title'); assert.equal('The Post Title', post.get('title')); }); QUnit.test('post is publishable', function(assert) { var post = new Post(); post.publish(); assert.ok(post.isPublished()); });
  83. defmodule PostTest do use ExUnit.Case test "sets the title" do

    post = %Post{} post = Map.put(post, :title, "The Post Title") assert "The Post Title" == post.title end test "publishes the post" do post = %Post{} post = Post.publish!(post) assert Post.published?(post) end end
  84. RECAP!

  85. Minitest é massa

  86. (RSpec também :P)

  87. Testar software vai além das nossas ferramentas

  88. As vezes é bom revisitar o encontro da teoria e

    da prática
  89. Obrigado! @lucasmazza https:/ /speakerdeck.com/lucas