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

テストを書かない言い訳をした結果②-負債にならないテストを求めて- / 2170726 #ios_test_night

takasek
July 26, 2017

テストを書かない言い訳をした結果②-負債にならないテストを求めて- / 2170726 #ios_test_night

iOS Test Night #5 - connpass
https://testnight.connpass.com/event/59283/
の発表資料です

---

# 参考リンク

takasek/XCJumpToTests: the script to jump files of Implementation⇄Tests
https://github.com/takasek/XCJumpToTests

typelift/SwiftCheck: QuickCheck for Swift
https://github.com/typelift/SwiftCheck

Property-Based Testing with SwiftCheck
https://news.realm.io/news/tryswift-tj-usiyan-property-based-testing-swiftcheck/

takasek

July 26, 2017
Tweet

More Decks by takasek

Other Decks in Programming

Transcript

  1. 5

  2. ςετॻ͖ͨ͘ͳ͍ཧ༝ᶄ ෛ࠴ʹͳΓ΍͍͢ "The dependencies between packages should be in the

    direction of the stability of the packages. A package should only depend upon packages that are more stable than it is. " 1 ύοέʔδͷґଘؔ܎͸ɺ҆ఆੑͷํ޲ʹґΒͳ͚Ε͹ͳΒͳ͍ɻ ύοέʔδ͸ɺΑΓ҆ఆͨ͠ύοέʔδʹͷΈґଘ͢΂͖ͩɻ ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹ- Robert C. Martin 1 Stable Dependencies Principle http://wiki.c2.com/?StableDependenciesPrinciple 13
  3. 14

  4. doctest ͱ͸ 2 doctest Ϟδϡʔϧ͸ɺର࿩త Python ηογϣϯͷΑ͏ʹݟ͑ΔςΩετΛ୳͠ग़͠ɺη ογϣϯͷ಺༰Λ࣮ߦͯ͠ɺͦ͜ʹॻ͔Ε͍ͯΔ௨Γʹৼ෣͏͔Λௐ΂·͢ɻ doctest ͸Ҏ

    ԼͷΑ͏ͳ༻్ʹΑ͘࢖ΘΕ͍ͯ·͢: 4 Ϟδϡʔϧͷ docstring (υΩϡϝϯςʔγϣϯจࣈྻ) தʹ͋Δର࿩࣮ߦྫͷ͢΂͕ͯ ॻ͔Ε͍ͯΔ௨Γʹಈ࡞͢Δ͔ݕূ͢Δ͜ͱͰɺdocstring ͷ಺༰͕࠷৽͔Ͳ͏͔νΣο Ϋ͢Δɻ 4 ςετϑΝΠϧ΍ςετΦϒδΣΫτதͷର࿩࣮ߦྫ͕ظ଴௨Γʹಈ࡞͢Δ͔Λݕূ͢Δ ͜ͱͰɺճؼςετΛ࣮ݱ͠·͢ɻ 4 ೖग़ྗྫΛ๛෋ʹ࢖ͬͨύοέʔδͷνϡʔτϦΞϧυΩϡϝϯτ͕ॻ͚·͢ɻೖग़ྗྫ ͱղઆจͷͲͪΒʹ஫໨͢Δ͔ʹΑͬͯɺυΩϡϝϯτ͸ʮಡΊΔςετʯʹ΋ʮ࣮ߦͰ ͖ΔυΩϡϝϯτʯʹ΋ͳΓ·͢ɻ 2 https://docs.python.jp/3/library/doctest.html 18
  5. doctest αϯϓϧίʔυ(python) def hoge(): """ >>> hoge() 'Hello World' """

    return "Hello world" if __name__ == "__main__": import doctest doctest.testmod() 19
  6. doctest ࣮ߦ݁Ռ [demo] % python example.py ********************************************************************** File "example.py", line

    4, in __main__.hoge Failed example: hoge() Expected: 'Hello World' Got: 'Hello world' ********************************************************************** 1 items had failures: 1 of 1 in __main__.hoge ***Test Failed*** 1 failures. 20
  7. doctest ݕূ݁Ռ def hoge(): """ >>> hoge() 'Hello World' """

    return "Hello world"ɹ! w ͕খจࣈʹͳͬͯΔʂʂ if __name__ == "__main__": import doctest doctest.testmod() 21
  8. SwiftDocTest ͸͜Μͳײ͡Ͱ࢖͏Β͍͠! /** :test: floor(CGPoint(x:10.9, y:-10.5)) :result: CGPoint(x:10, y:-11) */

    public func floor(value:CGPoint) -> CGPoint { return value.map(floor) } /** :test: ceil(CGPoint(x:10.9, y:-10.5)) :result: CGPoint(x:11, y:-10) */ public func ceil(value:CGPoint) -> CGPoint { return value.map(ceil) } ίϐϖͮ͠Βͦ͏… 25
  9. QuickCheck ͱ͸ 3 QuickCheckʢΫΠοΫνΣοΫʣ͸ɺ(...) HaskellͰॻ͔Εͨί ϯϏωʔλϥΠϒϥϦͰ͋Δɻ QuickCheckͰ͸ϓϩάϥϚ͸ؔ਺͕ຬͨ͢΂͖࿦ཧతੑ࣭ΛΞα ʔγϣϯͱͯ͠ॻ͘ɻςετ͸ؔ਺ͷҾ਺ͷܕ͕औΓಘΔ஋Λϥϯ μϜʹؔ਺ʹ༩͑Δ͜ͱͰɺΞαʔγϣϯ͕ࣦഊ͢Δ৚݅Λ୳ͦ͏ ͱࢼΈΔɻ(...)

    QuickCheck͸௨ৗͷϓϩάϥϜͷςετʹՃ͑ɺ ؔ਺࢓༷ͷࡦఆɺؔ਺͕͢Δ΂͖ڍಈΛυΩϡϝϯτͱͯࣔ͢͠ɺ ίϯύΠϥͷ࣮૷Λςετ͢Δɺͱ͍ͬͨ͜ͱʹ΋༗༻Ͱ͋Δɻ 3 https://ja.wikipedia.org/wiki/QuickCheck 30
  10. ૊Έ߹ΘͤͯδΣωϨʔλΛ࡞ͬͯ… let localEmail = allowedLocalCharacters .proliferateNonEmpty .suchThat({ $0[$0.index(before: $0.endIndex)] !=

    "." }) .map { String($0) } let hostname = Gen<Character>.one(of: [ lowerCaseLetters, numeric, Gen.pure("-"), ]).proliferateNonEmpty.map { String($0) } let tld = lowerCaseLetters .proliferateNonEmpty .suchThat({ $0.count > 1 }) .map { String($0) } let emailGen = glue([ localEmail, Gen.pure("@"), hostname, Gen.pure("."), tld ]) emailGen.generate // "q13vS#@s409pwr-plv90-w40--91-.ijtgmvoiljnticlggqlpw" emailGen.generate // "!'[email protected]" emailGen.generate // "46n}ZmEDg760&4L4RR#.Q'b{}[email protected]" 33
  11. ςετσʔλΛੜ੒͢ΔArbitraryΛ༻ҙͯ͠ struct ArbitraryEmail : Arbitrary { let email : String

    static var arbitrary : Gen<ArbitraryEmail> { return emailGen.map(ArbitraryEmail.init) } } 34
  12. ͦͷੑ࣭ΛνΣοΫ property("τοϓϨϕϧυϝΠϯͷμϝͳϝΞυ") <- forAll { (arbitrary : ArbitraryEmail) in !

    arbitrary.email.contains(".") }.expectFailure // +++ OK, failed as expected. Proposition: τοϓϨϕϧυϝΠϯͷͳ͍ϝΞυ // Falsifiable (after 1 test): // ArbitraryEmail(email: "{@3.ae") 35