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

Property based testing

Property based testing

How to improve your tests using the technique of property based testing.

Avatar for Suzanne Hamilton

Suzanne Hamilton

April 25, 2018

Other Decks in Technology

Transcript

  1. class GildedRose(object): def __init__(self, name, quality, days_remaining): self.name = name

    self.quality = quality self.days_remaining = days_remaining def tick(self): # ...
  2. class GildedRose(object): def __init__(self, name, quality, days_remaining): self.name = name

    self.quality = quality self.days_remaining = days_remaining def tick(self): # ...
  3. class GildedRose(object): def __init__(self, name, quality, days_remaining): self.name = name

    self.quality = quality self.days_remaining = days_remaining def tick(self): # ...
  4. def tick(self): if self.name != "Aged Brie" and self.name !=

    "Backstage passes to a TAFKAL80ETC concert": if self.quality > 0: if self.name != "Sulfuras, Hand of Ragnaros": self.quality = self.quality - 1 else: if self.quality < 50: self.quality = self.quality + 1 if self.name == "Backstage passes to a TAFKAL80ETC concert": if self.days_remaining < 11: if self.quality < 50: self.quality = self.quality + 1 if self.days_remaining < 6: if self.quality < 50: self.quality = self.quality + 1 if self.name != "Sulfuras, Hand of Ragnaros": self.days_remaining = self.days_remaining - 1 if self.days_remaining < 0: if self.name != "Aged Brie": if self.name != "Backstage passes to a TAFKAL80ETC concert": if self.quality > 0: if self.name != "Sulfuras, Hand of Ragnaros": self.quality = self.quality - 1 else: self.quality = self.quality - self.quality else: if self.quality < 50: self.quality = self.quality + 1
  5. from hypothesis import given from hypothesis.strategies import integers, text @given(text(),

    integers(), integers()) def test_lowers_days_remaining(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() assert item.days_remaining < days_remaining
  6. from hypothesis import given from hypothesis.strategies import integers, text @given(text(),

    integers(), integers()) def test_lowers_days_remaining(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() assert item.days_remaining < days_remaining
  7. from hypothesis import given from hypothesis.strategies import integers, text @given(text(),

    integers(), integers()) def test_lowers_days_remaining(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() assert item.days_remaining < days_remaining
  8. from hypothesis import given from hypothesis.strategies import integers, text @given(text(),

    integers(), integers()) def test_lowers_days_remaining(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() assert item.days_remaining < days_remaining
  9. from hypothesis import given from hypothesis.strategies import integers, text @given(text(),

    integers(), integers()) def test_lowers_days_remaining(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() assert item.days_remaining < days_remaining
  10. GILDED ROSE REQUIREMENTS ‣ Quality is never more than 50

    ‣ "Aged Brie" increases in quality the older it gets
  11. def item_name(): return one_of( text(), sampled_from([ "Sulfuras, Hand of Ragnaros",

    "Backstage passes to a TAFKAL80ETC concert", "Aged Brie" ]) )
  12. def item_name(): return one_of( text(), sampled_from([ "Sulfuras, Hand of Ragnaros",

    "Backstage passes to a TAFKAL80ETC concert", "Aged Brie" ]) )
  13. ===================================== FAILURES ====================================== _____________________________ test_quality_limit_is_50 ______________________________ @given(text(), integers(), integers()) >

    def test_quality_limit_is_50(name, quality, days_remaining): tests/test_gilded_rose.py:34: ... Stack trace name = '', quality = 53, days_remaining = 0 @given(text(), integers(), integers()) def test_quality_limit_is_50(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() > assert item.quality <= 50 E AssertionError: assert 51 <= 50 E + where 51 = GildedRose(name: '', quality: 51, days_remaining: -1).quality tests/test_gilded_rose.py:38: AssertionError ------------------------------------ Hypothesis ------------------------------------- Falsifying example: test_quality_limit_is_50(name='', quality=53, days_remaining=0) ======================== 1 failed, 1 passed in 0.21 seconds =========================
  14. ===================================== FAILURES ====================================== _____________________________ test_quality_limit_is_50 ______________________________ @given(text(), integers(), integers()) >

    def test_quality_limit_is_50(name, quality, days_remaining): tests/test_gilded_rose.py:34: ... Stack trace name = '', quality = 53, days_remaining = 0 @given(text(), integers(), integers()) def test_quality_limit_is_50(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() > assert item.quality <= 50 E AssertionError: assert 51 <= 50 E + where 51 = GildedRose(name: '', quality: 51, days_remaining: -1).quality tests/test_gilded_rose.py:38: AssertionError ------------------------------------ Hypothesis ------------------------------------- Falsifying example: test_quality_limit_is_50(name='', quality=53, days_remaining=0) ======================== 1 failed, 1 passed in 0.21 seconds =========================
  15. ===================================== FAILURES ====================================== _____________________________ test_quality_limit_is_50 ______________________________ @given(text(), integers(), integers()) >

    def test_quality_limit_is_50(name, quality, days_remaining): tests/test_gilded_rose.py:34: ... Stack trace name = '', quality = 53, days_remaining = 0 @given(text(), integers(), integers()) def test_quality_limit_is_50(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() > assert item.quality <= 50 E AssertionError: assert 51 <= 50 E + where 51 = GildedRose(name: '', quality: 51, days_remaining: -1).quality tests/test_gilded_rose.py:38: AssertionError ------------------------------------ Hypothesis ------------------------------------- Falsifying example: test_quality_limit_is_50(name='', quality=53, days_remaining=0) ======================== 1 failed, 1 passed in 0.21 seconds =========================
  16. ===================================== FAILURES ====================================== _____________________________ test_quality_limit_is_50 ______________________________ @given(text(), integers(), integers()) >

    def test_quality_limit_is_50(name, quality, days_remaining): tests/test_gilded_rose.py:34: ... Stack trace name = '', quality = 53, days_remaining = 0 @given(text(), integers(), integers()) def test_quality_limit_is_50(name, quality, days_remaining): item = GildedRose(name, quality, days_remaining) item.tick() > assert item.quality <= 50 E AssertionError: assert 51 <= 50 E + where 51 = GildedRose(name: '', quality: 51, days_remaining: -1).quality tests/test_gilded_rose.py:38: AssertionError ------------------------------------ Hypothesis ------------------------------------- Falsifying example: test_quality_limit_is_50(name='', quality=53, days_remaining=0) ======================== 1 failed, 1 passed in 0.21 seconds =========================
  17. Trying example: test_quality_limit_is_50(name='\U000c762b\U000ac9f5\U000f15be\x00\U000b83a4.\U0009c1f0', quality=68, days_remaining=-4089) ... stack trace ... AssertionError:

    assert 66 <= 50 ... lots of attempts at simplification ... Falsifying example: test_quality_limit_is_50(name='', quality=53, days_remaining=0)
  18. Python Hypothesis JavaScript JSVerify Java QuickTheories Scala ScalaCheck C# and

    F# FsCheck PHP Eris Clojure test.check (Ruby) Hypothesis for Ruby (pre-alpha) SOME LIBRARIES
  19. READ MORE ▸ Other libraries:
 https://hypothesis.works/articles/ quickcheck-in-every-language/ ▸ Other property

    tactics:
 https://fsharpforfunandprofit.com/posts/ property-based-testing-2/ @suzyhamilton