Last active
July 22, 2019 13:48
-
-
Save Vinai/a2f9b8b3d42b08c4e4c69e7b1685d48e to your computer and use it in GitHub Desktop.
Example of property based tests for a simple algorithm in Clojure and in PHP.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns example.core | |
(:require [clojure.test :refer :all] | |
[clojure.test.check :as tc] | |
[clojure.test.check.generators :as gen] | |
[clojure.test.check.properties :as prop])) | |
;; ----------------------------------------------------------------------- | |
;; Application code to test | |
(defn includes? [needle haystack] | |
(some #{needle} haystack)) | |
;; function to be tested | |
(defn pick-create-list-strategy [create-lists] | |
(cond | |
(includes? "AUTO" create-lists) "AUTO" | |
(includes? "MANUAL" create-lists) "MANUAL" | |
:else "NONE")) | |
;; ----------------------------------------------------------------------- | |
;; Generators | |
;; generator for a vec of random strings (except AUTO or MANUAL) | |
(def generate-input-without-manual-or-auto | |
(gen/such-that #(not (or (includes? "AUTO" %) (includes? "MANUAL" %))) (gen/vector gen/string))) | |
;; generator for a vec of random strings that always also includes MANUAL | |
(def generate-input-with-manual | |
(gen/bind generate-input-without-manual-or-auto | |
(fn [others] | |
(gen/shuffle (conj others "MANUAL"))))) | |
;; generator for a vec of random strings that always includes AUTO and might also include MANUAL | |
(def generate-input-with-auto | |
(gen/bind (gen/one-of [generate-input-without-manual-or-auto generate-input-with-manual]) | |
(fn [others] | |
(gen/shuffle (conj others "AUTO"))))) | |
;; ----------------------------------------------------------------------- | |
;; Tests | |
(deftest test-list-creation-strategy-selection | |
(testing "If no AUTO or MANUAL is present then NONE is returned" | |
(let [property (prop/for-all [input generate-input-without-manual-or-auto] | |
(= "NONE" (pick-create-list-strategy input)))] | |
(is (:result (tc/quick-check 500 property))))) | |
(testing "If MANUAL is present but no AUTO then MANUAL is returned" | |
(let [property (prop/for-all [input generate-input-with-manual] | |
(= "MANUAL" (pick-create-list-strategy input)))] | |
(is (:result (tc/quick-check 500 property))))) | |
(testing "If AUTO is present AUTO is returned, even if MANUAL is also present" | |
(let [property (prop/for-all [input generate-input-with-auto] | |
(= "AUTO" (pick-create-list-strategy input)))] | |
(is (:result (tc/quick-check 500 property)))))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use PHPUnit\Framework\TestCase; | |
use Eris\Generator; | |
use function array_map as map; | |
/* Function under test */ | |
function pickCreateListStrategy(array $createListings) | |
{ | |
$hasAuto = in_array('AUTO', $createListings, true); | |
$hasManual = in_array('MANUAL', $createListings, true); | |
return $hasAuto ? 'AUTO' : ($hasManual ? 'MANUAL' : 'NONE'); | |
} | |
class Example extends TestCase | |
{ | |
use \Eris\TestTrait; | |
/** | |
* @before | |
*/ | |
public function configureEris() | |
{ | |
$this->limitTo(500); | |
} | |
/* Generators */ | |
private function generateInputWithoutManualOrAuto(): Generator { | |
return Generator\suchThat( | |
function (array $input): bool { | |
return !(in_array('AUTO', $input, true) || in_array('MANUAL', $input, true)); | |
}, | |
Generator\seq(Generator\string()) | |
); | |
} | |
private function generateInputWithManual(): Generator | |
{ | |
return Generator\bind( | |
$this->generateInputWithoutManualOrAuto(), | |
function (array $others) { | |
$others[] = 'MANUAL'; | |
shuffle($others); | |
return Generator\constant($others); | |
} | |
); | |
} | |
private function generateInputWithAuto(): Generator | |
{ | |
return Generator\bind( | |
Generator\oneOf($this->generateInputWithoutManualOrAuto(), $this->generateInputWithManual()), | |
function (array $others) { | |
$others[] = 'AUTO'; | |
shuffle($others); | |
return Generator\constant($others); | |
} | |
); | |
} | |
/* Tests */ | |
public function testIfNoAutoOrManualIsPresent_NoneIsReturned() | |
{ | |
$property = $this->forAll($this->generateInputWithoutManualOrAuto()); | |
$property(function (array $input): void { | |
$this->assertSame('NONE', pickCreateListStrategy($input)); | |
}); | |
} | |
public function testIfManualIsPresent_ManualIsReturned() | |
{ | |
$property = $this->forAll($this->generateInputWithManual()); | |
$property(function (array $input): void { | |
$this->assertSame('MANUAL', pickCreateListStrategy($input)); | |
}); | |
} | |
public function testIfAutoIsPresent_AutoIsReturned() | |
{ | |
$property = $this->forAll($this->generateInputWithAuto()); | |
$property(function (array $input): void { | |
$this->assertSame('AUTO', pickCreateListStrategy($input)); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: Clojure 1.10 runs the 1500 tests in total in 0.8s, PHP 7.2 takes 57s on my MBP.