% module: lambda_unit_tests.pl % date: November 16, 2005 % author: unit_test_case_generator % copyright (c) 2005, Cotillion Group, Inc. All rights reserved. % synopsis: Unit test cases for exported predicates in lambda :- module(lambda_unit_tests, [ unit_test_case_suite_brief/2, unit_test_case_suite/2, tautology/4, what_unit_tests/1 ]). % modified: November 19, 2005, DMA (Douglas M. Auclair) % changed: fleshed out suite with more boundary condition tests % modified: November 16, 2005, DMA % changed: Added implementation of unit tests; added units for test/2 :- use_module(library(unit_test_utils), [ extract_names_from/3, add_to_successes/3, add_to_failures/3 ]). :- use_module(library(lambda), [test/2, apply/3]). :- use_module(library(syntax), [(~)/1]). :- op(900, fy, ~). unit_test_case_suite_brief(Briefs, Failures) :- % Gives only the names (and not other information) on the tests that % succeeded; failures reported with other information included. unit_test_case_suite(Successes, Failures), extract_names_from(Successes, Briefs, []). unit_test_case_suite(Successes, Failures) :- % Runs all the unit test cases and reports on successes and failures what_unit_tests(tautologies(TestSets)), test_each_set(TestSets, tests_complete([], []), tests_complete(Successes, Failures)). what_unit_tests(tautologies([ test_set(test/2, [nominal(k(predicate(_, true), arg(apple_pi))), nominal(i(predicate(A, A < 10), arg(5))), nominal(k(complement(_, fail), arg(chicken_pol_pot_pie))), nominal(i(complement(B, B > 10), arg(3))), extrinsic(k(predicate(_, fail), arg(wensleydale)), reason(goal_failed)), extrinsic(i(predicate(C, C < 10), arg(11)), reason(goal_failed)), extrinsic(k(complement(_, true), arg(cheddar)), reason(goal_succeeded)), extrinsic(i(complement(D, D > 10), arg(12)), reason(goal_succeeded))]), test_set(apply/3, [nominal(args(lambda(X, X+1), arg(3), answer(4))), nominal(args(lambda(_, 6 * 7), arg(33), answer(42)))])])). % Indicates what unit tests cases are available for this module and % the expected pass/fail-for-reason result for each unit test. % ------------------------------------------------------------------------ % test/2 unit test cases tautology(test/2, nominal(k(Predicate, arg(Arg))), true, true) :- % Ensures predicate/2 and complement/2 work as they should, where Arg % has no bearing on the truth result. The K combinator drops the % second composed function, so k/2 is used descriptively here to % show Predicate's intent. test(Predicate, Arg). % a tautology to test test/2 ... HA! tautology(test/2, nominal(i(Predicate, arg(Arg))), true, true) :- % Same guarantee: make sure predicate/2 and complement/2 work. The % I combinator (the identity function) is a pass-thru function: its % argument is its answer, so i(Predicate) = Predicate, which is a very % indirect way of stating that Predicate's /Arg/ is actually used % by (instead of unceremoniously dropped by) Predicate. test(Predicate, Arg). tautology(test/2, extrinsic(Test, _), fail, fail) :- % Make sure test/2 fails appropriately as well Test =.. [_, Predicate, arg(Arg)], ~ test(Predicate, Arg). % ------------------------------------------------------------------------ % apply/3 unit test case tautology(apply/3, nominal(args(Lambda, arg(Arg), answer(Actual))), Actual, Actual) :- % Exercises apply/3, ensuring it resolves to the expected Answer apply(Lambda, Arg, Answer), Actual is Answer. % ------------------------------------------------------------------------ % INTERNAL IMPLEMENTATION PREDICATES % test_each_set/3 breaks the unit tests down by predicate test_each_set([]) --> []. test_each_set([test_set(Pred, Tests)|Sets]) --> test_each_case(Pred, Tests), test_each_set(Sets). % test_each_case/4 runs a unit test and records the result % (pass/fail) by putting it in an appropriate result list. test_each_case(_, []) --> []. test_each_case(Pred, [Test|Tests]) --> ({ tautology(Pred, Test, Expected, Actual) } -> add_to_successes(test_result(Pred, Test, Expected, Actual)) ; add_to_failures(test_result(Pred, Test, _, failure))), test_each_case(Pred, Tests).