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

TDD using Minitest

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for diogenes diogenes
August 08, 2015
360

TDD using Minitest

Talk gave in the 1º Tech Day, GURU-PR 2015 @ EBANX Headquarters

Avatar for diogenes

diogenes

August 08, 2015
Tweet

Transcript

  1. Agenda • Test-Driven Development ◦ Overview ◦ Why to use

    • Minitest ◦ Overview ◦ How to use
  2. "... a software development process that relies on the repetition

    of a very short development cycle: first the developer writes an (initially failing) automated test case that defines a desired improvement, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards." Wikipedia
  3. Better Code Design • Focus on How to use, its

    Interface/API "the expected behavior" rather than "how this is implemented"
  4. Better Code Design • Feedback from Test Smells ◦ Over-mocking

    ◦ Hard to write tests ◦ Too much responsibility ◦ Too many assertions
  5. Code Design Feedback - Example describe User do subject {

    User.new } describe "its registration process" do let(:address) { AnObject.new } let(:phone) { Another.new } let(:children) { OtherOne.new } let(:mailer) { AnyObject.new } # etc... it "saves the related address" do # Test saving of the address end it "saves the related children" do # Test saving of children end it "saves the related phones" ... it "saves the user" ... it "sends and email to the user" ... end end
  6. What's Minitest? • Replacement for Ruby 1.8's test/unit ◦ Originally

    90 lines of code • Available built-in with Ruby 1.9 • Available as a gem • Meant to be small, clean, and very fast
  7. What's Minitest? 6 parts • runner: The heart of the

    machine • minitest/unit: TDD API • minitest/spec: BDD API • minitest/mock: Simple mocking API • minitest/pride: IO pipelining example • minitest/bench: Abstract benchmark API
  8. Minitest Philosophy • Less is more ◦ Very small in

    comparison with RSpec ◦ Very Fast • Isolated Tests ◦ Test Randomization: Prevents order dependencies • Indirection is the Enemy ◦ Failures pointing to the failure
  9. minitest positive assertions assert assert_block * 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 *
  10. minitest negative assertions 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
  11. minitest expectations must_be must_be_close_to must_be_empty must_be_instance_of must_be_kind_of must_be_nil must_be_same_as must_be_silent

    * must_be_within_delta must_be_within_epsilon must_equal must_include must_match must_output * must_raise * must_respond_to must_send * must_throw *
  12. minitest negative expectations wont_be wont_be_close_to wont_be_empty wont_be_instance_of wont_be_kind_of wont_be_nil wont_be_same_as

    wont_be_within_delta wont_be_within_epsilon wont_equal wont_include wont_match wont_respond_to
  13. Minitest Ecosystem minitest-chef-handler minitest-reporters minitest-rails guard-minitest minitest-spec-rails minitest-capybara spork-minitest minitest-metadata

    minitest-rails-capybara minitest-matchers capybara_minitest_spec minitest-colorize minitest-rg minitest-ci (many more…)
  14. Red - Write the test require 'minitest/autorun' describe Article do

    subject { Article.new } it "can be posted on Twitter" do subject.post_on_twitter subject.twitted?.must_equal true end end
  15. Red - See it failing $ ruby -Ilib spec/article_spec.rb Run

    options: --seed 34214 1) Error: Article#test_0001_can be posted on Twitter: NoMethodError: undefined method `post_on_twitter' for #<Article:0x000000012c75d0> spec/article_spec.rb:8:in `block (2 levels) in <main>' 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
  16. Red - See it failing $ ruby -Ilib spec/article_spec.rb Run

    options: --seed 47611 1) Error: Article#test_0001_can be posted on Twitter: NoMethodError: undefined method `twitted?' for #<Article: 0x00000002347130> spec/article_spec.rb:9:in `block (2 levels) in <main>' 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
  17. Red - See it failing $ ruby -Ilib spec/article_spec.rb Run

    options: --seed 19132 # Running: F... 1) Failure: Article#test_0001_can be posted on Twitter [spec/article_spec. rb:9]: Expected: true Actual: nil
  18. Green - Implements the code class Article def post_on_twitter #

    Logic to post the article (...) @twitted = true end end
  19. Green - See it passing % ruby -Ilib spec/article_spec.rb Run

    options: --seed 37685 # Running: ......................................................... ............. (etc) Finished in 0.107130s, 1446.8403 runs/s, 2959.0217 assertions/s. 155 runs, 317 assertions, 0 failures, 0 errors, 0 skips
  20. Green - See it passing % ruby -Ilib spec/article_spec.rb Run

    options: --seed 37685 # Running: ......................................................... ............. (etc) Finished in 0.107130s, 1446.8403 runs/s, 2959.0217 assertions/s. 155 runs, 317 assertions, 0 failures, 0 errors, 0 skips