[m-users.] Basic Unit Test Framework

Dirk Ziegemeyer dirk at ziegemeyer.de
Sun Jul 19 06:58:48 AEST 2015

Thank your for the clarification and sorry for my late reply.

I understand that my current testing approach is different.

I pass the predicate-under-test as a parameter to a test-predicate together with the expected result.

For the DCG parser, I use two different types of test-predicates:
1. takes the chars-to-be-parsed as a parameter. This is convenient only for small strings.
2. takes as parameter a name of a file, which is opened by the test predicate and contains the chars-to-be-parsed

My test-predicates also differ by the type of the expected result, which are:
a) bool for a semidet predicate with no output (e.g. a DCG predicate that just evaluates to true if the chars-to-be-parsed conform to the DCG grammar rule)
b) maybe(Result) for a semidet predicate with one output parameter (e.g. a DCG predicate that returns a parsing result if the chars-to-be-parsed conform to the DCG grammar rule)



> Am 14.07.2015 um 01:35 schrieb Charles Shuller <charles.shuller at gmail.com>:
> > 3) Hard to get a message about what failed if the predicate only succeeds of fails.  I save off results instead of pushing IO into the test harness though.   I felt it made more sense.
> I also don’t like pushing IO through the test cases, but I didn’t accomplish to put test cases into a list. After reading in the reference manual section 8.3, that higher-order terms can cause problems in polymorphic collection types, I gave up my try to collect test cases in a list.
> I'm not using Polymorphism.
> :- type test_result
> 	---> test_result(result_test_name::string,
> 		         result_test_disposition::test_disposition).
> Eventually, I'll want to flesh that out with things like the hostname, startTime, stopTime, etc...  but this is all I needed for no
> For a simple XML parser, I wrote dozens of test cases like these:
> %% testDCG(TestNo, DCG-predicate, InputToBeParsed, ExpectedResult, !IO)
> testDCG(1, nameStartChar, ":", yes(':'), !IO),
> testDCG(2, nameStartChar, "-", no, !IO),
> testDCG(3, nameChar, "-", yes('-'), !IO),
> testDCG(4, name, "Name", yes("Name"), !IO),
> testDCG(5, attValue, "\"AttValue\"", yes("AttValue"), !IO),
> testDCG(6, attribute, "attribute=\"Value\"",
>     yes({"attribute", "Value"}), !IO),
> I don’t understand the syntax of test_case yet. Could you please give me an example, how I can write a list of test cases for different DCG predicates?
> You don't pass in the predicate-under-test as a parameter, instead you build a test predicate and call predicate-under-test from there.
> Below is an example of test cases defined in terms of named predicates, instead of lambdas.   I am currently No Good at DCGs, but I'll write something similar to what I think you're first test does  and hopefully you can figure out how to adapt it.
> :- pred pass_test(test_disposition::out) is det.
> pass_test(Disposition) :-
> 	Disposition = pass.
> :- pred fail_test(test_disposition::out) is det.
> fail_test(Disposition) :-
> 	Disposition = fail("Fail tests aways Fail").
> :- pred name_start_test(test_disposition::out) is det.
> name_start_test(Disposition) :-        
>          nameStartChar(":someString" OutStartChar),
>          (
>           if   OutStartChar = ":" 
>           then Disposition = pass
>           else Disposition = fail("Expected StartChar to be : But got " ++ OutStartChar ++ " instead"
>          ).
> TestList = [
> 		    test_case("PassTest", pass_test),
> 		    test_case("FailTest", fail_test),
>                     test_case("NameStartTest), name_start_test)
>            ]
> the if...then...else in name_start_test could have been a call to assertions.are_equal instead:
> name_start_test(Disposition)
>        nameStartChar(":someString", OutStartChar),
>        assertions.are_equal(univ(":"), univ(OutStartChar), Disposition).
> Cheers!
> Charles

More information about the users mailing list