Created
February 11, 2015 14:50
-
-
Save turanct/129a6ed97ec3543ebafd to your computer and use it in GitHub Desktop.
Simple test framework, functional programming style
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 | |
function within($topic, ...$features) | |
{ | |
return function($do = 'getFailedAssertions') use ($topic, $features) { | |
if ($do === 'getName') { | |
return $topic; | |
} elseif ($do === 'getFailedAssertions') { | |
return array_reduce( | |
$features, | |
function($failedAssertions, $feature) { | |
return array_merge( | |
$failedAssertions, | |
array_map( | |
function($assertion) use ($feature) { | |
return array($assertion, $feature); | |
}, | |
$feature('getFailedAssertions') | |
) | |
); | |
}, | |
array() | |
); | |
} elseif ($do === 'numberOfFeatures') { | |
return count($features); | |
} elseif ($do === 'numberOfAssertions') { | |
return array_reduce( | |
$features, | |
function($number, $feature) { | |
return $number + $feature('numberOfAssertions'); | |
}, | |
0 | |
); | |
} else { | |
throw new InvalidArgumentException('Invalid argument ' . $do); | |
} | |
}; | |
} | |
function describe($feature, ...$assertions) | |
{ | |
return function($do = 'getFailedAssertions') use ($feature, $assertions) { | |
if ($do === 'getName') { | |
return $feature; | |
} elseif ($do === 'getFailedAssertions') { | |
return array_filter( | |
$assertions, | |
function($assertion) { | |
return !$assertion('assert'); | |
} | |
); | |
} elseif ($do === 'numberOfAssertions') { | |
return count($assertions); | |
} else { | |
throw new InvalidArgumentException('Invalid argument ' . $do); | |
} | |
}; | |
} | |
function it($doesThis, $correctly) | |
{ | |
return function($do = 'assert') use ($doesThis, $correctly) { | |
if ($do === 'assert') { | |
return (bool) $correctly; | |
} elseif ($do === 'getDescription') { | |
return (string) $doesThis; | |
} else { | |
throw new InvalidArgumentException('Invalid argument ' . $do); | |
} | |
}; | |
} | |
function testResults(array $topics) | |
{ | |
return function($do = '') use ($topics) { | |
if ($do === 'numberOfTopics') { | |
return count($topics); | |
} elseif ($do === 'numberOfFeatures') { | |
return array_reduce( | |
$topics, | |
function($number, $topic) { | |
return $number + $topic('numberOfFeatures'); | |
}, | |
0 | |
); | |
} elseif ($do === 'numberOfAssertions') { | |
return array_reduce( | |
$topics, | |
function($number, $topic) { | |
return $number + $topic('numberOfAssertions'); | |
}, | |
0 | |
); | |
} elseif ($do === 'failedAssertions') { | |
return array_reduce( | |
$topics, | |
function($failedAssertions, $topic) { | |
$assertions = $topic('getFailedAssertions'); | |
$assertions = array_map( | |
function($assertion) use ($topic) { | |
$assertion[] = $topic; | |
return $assertion; | |
}, | |
$assertions | |
); | |
return array_merge($failedAssertions, $assertions); | |
}, | |
array() | |
); | |
} else { | |
throw new InvalidArgumentException('Invalid argument ' . $do); | |
} | |
}; | |
} | |
function displayTestResults($testResults) | |
{ | |
$output = ''; | |
$output .= 'topics: ' . $testResults('numberOfTopics') . "\n"; | |
$output .= 'features: ' . $testResults('numberOfFeatures') . "\n"; | |
$output .= 'assertions: ' . $testResults('numberOfAssertions') . "\n"; | |
$output .= "\n"; | |
$output .= implode( | |
"\n", | |
array_map( | |
function($assertion) { | |
return failedOutput($assertion[2], $assertion[1], $assertion[0]); | |
}, | |
$testResults('failedAssertions') | |
) | |
); | |
$output .= "\n"; | |
echo $output; | |
} | |
function failedOutput($topic, $feature, $assertion) | |
{ | |
return 'FAILED: ' | |
. $topic('getName') | |
. ': ' . $feature('getName') | |
. ' ' . $assertion('getDescription') | |
; | |
} | |
function getTopics() | |
{ | |
$files = glob('topic*.php'); | |
return array_map( | |
function($file) { | |
return include($file); | |
}, | |
$files | |
); | |
} |
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 | |
require_once 'functional-tests.php'; | |
displayTestResults(testResults(getTopics())); |
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 | |
return within("calculus", | |
describe("addition", | |
it("adds two numbers", (1 + 1 == 3)), | |
it("is difficult", false), | |
it("adds three numbers", (1 + 1 + 1 == 3)) | |
), | |
describe("subtraction", | |
it("looks strange", true), | |
it("subtracts two numbers", (3 - 2 == 1)) | |
) | |
); |
- Line 60:
$correctly
should probably be a callback instead of a bool. - rename
$do
to$message
- Instead of all the ugly if/elseifs, abstract the pattern into a function called
dispatch
. See https://github.com/mathiasverraes/lambdalicious/blob/master/src/Verraes/Lambdalicious/datastructures.php#L19-L28 for an example
you're right about those 3 things. Also, i didn't see the dispatch method yet, it's really quite elegant!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
running
php run-tests.php
will produce this output:It will also work with multiple topic-* files