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

Property Based Testing on Rails

Property Based Testing on Rails

The Ruby community is known by its strong culture of testing, but this is not an excuse to refuse alternative approaches. One of these are Property Testing. In those tools we do not express examples, but the possible input formats; instead of specific outputs, characteristics that must remain true. In this way our tools are capable of exhaustively generate test cases and look for failures. In this talk we'll see how to create lean suites with wide coverage using Clojure's power to test a Rails application.

Video [pt-br]: https://www.youtube.com/watch?v=WKuZWzi2oRQ

83aaddfb8a64b3fcdda06d8562013b7c?s=128

Andrew Rosa

March 07, 2015
Tweet

Transcript

  1. TESTES DE PROPRIEDADE (((on Rails)))

  2. Eu ♥ Ruby!

  3. Eu ♥ Clojure!

  4. (((((((((((((yep!)))))))))))))

  5. 4:20 PM

  6. Andrew Rosa @_andrewhr

  7. None
  8. Prop… what?

  9. it "sorts a list" do v = [3, 1, 2]

    s = sort(v) expect(s).to eq([1, 2, 3]) end
  10. it "sorts a list" do v = [3, 1, 2]

    s = sort(v) expect(s).to eq([1, 2, 3]) end
  11. it "sorts a list" do v = [3, 1, 2]

    s = sort(v) expect(s).to eq([1, 2, 3]) end
  12. it "sorts a list" do v = [3, 1, 2]

    s = sort(v) expect(s).to eq([1, 2, 3]) end
  13. it "sorts a list" do v = [3, 1, 2]

    s = sort(v) expect(s).to eq([1, 2, 3]) end
  14. EXEMPLO

  15. #sorts ascending sorts an empty list sorts a list with

    single item sorts a list with multiple items ! Finished in 0.00179 seconds 3 examples, 0 failures
  16. PROPRIEDADE

  17. ∀ a, b → int, int (a + b) =

    (b + a)
  18. ∀ a, b → int, int (a + b) =

    (b + a)
  19. ∀ a, b → int, int (a + b) =

    (b + a)
  20. ∀ a, b → int, int (a + b) =

    (b + a)
  21. ∀ a, b → int, int (a + b) =

    (b + a)
  22. ∀ a, b → int, int (a + b) =

    (b + a)
  23. INVARIANTE

  24. ∀ v → vector int each pair a, b in

    sort(v) a <= b
  25. ∀ v → vector int each pair a, b in

    sort(v) a <= b
  26. ∀ v → vector int each pair a, b in

    sort(v) a <= b
  27. ∀ v → vector int each pair a, b in

    sort(v) a <= b
  28. ∀ v → vector int each pair a, b in

    sort(v) a <= b
  29. ∀ v → vector int each pair a, b in

    sort(v) a <= b
  30. GERADORES

  31. ∀ v → vector int each pair a, b in

    sort(v) a <= b
  32. ∀ v → vector int each pair a, b in

    sort(v) a <= b v → [] v → [-1] v → [2 -1 1 -1 -2 5] v → [4] v → [7 9 -4 -4] …
  33. CONTRA-EXEMPLO a.k.a. uma falha

  34. [23 -17 8 -20 -35 -25 -22 10 11 -19

    9 -3 -42 -33 -34 -11 7 -28 -5 38 39 -26 -29 42 0 -41 33 -35 19]
  35. SHRINKING

  36. !

  37. !

  38. [23 -17 8 -20 -35 -25 -22 10 11 -19

    9 -3 -42 -33 -34 -11 7 -28 -5 38 39 -26 -29 42 0 -41 33 -35 19]
  39. [42 0]

  40. def sort(v) if v.include?(42) v else v.sort end end

  41. COBERTURA

  42. 01 def sort(v) 02 if v.include?(42) 03 v 04 else

    05 v.sort 06 end 07 end
  43. 01 def sort(v) 02 if v.include?(42) 03 v 04 else

    05 v.sort 06 end 07 end v1 v2 v3 v4 …
  44. PROPRIEDADE EXEMPLO

  45. None
  46. EXEMPLO in = “hello world!” out = “SGVsbG8gd29ybGQ=\n” expect(encode(in)).to eq(out)

  47. PROPRIEDADE ∀ in → string in = decode(encode(in))

  48. QuickCheck http://www.cse.chalmers.se/~rjmh/QuickCheck

  49. Erlang QuickCheck http://www.quviq.com/products/erlang-quickcheck

  50. Rantly https://github.com/hayeah/rantly

  51. test.check https://github.com/clojure/test.check

  52. …on Rails?

  53. (+ clj-webdriver test.check)

  54. Rails App Banco de Dados Testes Selenium* API webdriver JDBC

    UI
  55. {:action :add-entry :via :ui :value 2995}

  56. (defmulti dispatch! :action) ! (defmethod dispatch! :add-entry [action] (to base-url)

    (input-text “#entry_value" (str (:value action))) (submit "#entry_value"))
  57. (defspec track-all-money-on-database 25 (for-all [actions gen-actions] (prepare-database! test-db) (dispatch-all! actions)

    (= (total-of actions) (total-recorded-in test-db))))
  58. (defspec track-all-money-on-database 25 (for-all [actions gen-actions] (prepare-database! test-db) (dispatch-all! actions)

    (= (total-of actions) (total-recorded-in test-db))))
  59. (defspec track-all-money-on-database 25 (for-all [actions gen-actions] (prepare-database! test-db) (dispatch-all! actions)

    (= (total-of actions) (total-recorded-in test-db))))
  60. (defspec track-all-money-on-database 25 (for-all [actions gen-actions] (prepare-database! test-db) (dispatch-all! actions)

    (= (total-of actions) (total-recorded-in test-db))))
  61. (defspec track-all-money-on-database 25 (for-all [actions gen-actions] (prepare-database! test-db) (dispatch-all! actions)

    (= (total-of actions) (total-recorded-in test-db))))
  62. (defspec track-all-money-on-database 25 (for-all [actions gen-actions] (prepare-database! test-db) (dispatch-all! actions)

    (= (total-of actions) (total-recorded-in test-db))))
  63. (defspec track-all-money-on-database 25 (for-all [actions gen-actions] (prepare-database! test-db) (dispatch-all! actions)

    (= (total-of actions) (total-recorded-in test-db))))
  64. https://github.com/andrewhr/rails-test-check-example

  65. Ashton Kemerling https://www.youtube.com/watch?v=HXGpBrmR70U

  66. Ashton Kemerling https://www.youtube.com/watch?v=HXGpBrmR70U Também no Ruby Rogues #196 ;-)

  67. Simulant https://github.com/Datomic/simulant

  68. IDÉIAS LÁ FORA Wild, Wild West

  69. Obrigado! Andrew @_andrewhr