root/trunk/library/lgtunit.lgt

Revision 4224, 3.9 KB (checked in by pmoura, 7 months ago)

Corrected a bug in the library object "lgtunit" when running "throws" tests (make sure the generated exception is subsumed by the expected exception). Added a "lgtunit_loader" loader utility file for loading the Logtalk unit test library.

  • Property svn:eol-style set to native
Line 
1
2:- object(lgtunit).
3
4    :- info([
5        version is 0.3,
6        author is 'Paulo Moura',
7        date is 2008/04/25,
8        comment is 'Logtalk unit test framework.']).
9
10    :- uses(term, [subsumes/2]).
11
12    :- public(succeeds/2).
13    :- mode(succeeds(+atom, @callable), zero_or_more).
14    :- info(succeeds/2, [
15        comment is 'Defines a test goal which is expected to succeed.',
16        argnames is ['Identifier', 'Goal']]).
17
18    :- public(fails/2).
19    :- mode(fails(+atom, @callable), zero_or_more).
20    :- info(fails/2, [
21        comment is 'Defines a test goal which is expected to fail.',
22        argnames is ['Identifier', 'Goal']]).
23
24    :- public(throws/3).
25    :- mode(throws(+atom, @callable, @nonvar), zero_or_more).
26    :- info(throws/3, [
27        comment is 'Defines a test goal which is expected to throw an error.',
28        argnames is ['Identifier', 'Goal', 'Error']]).
29
30    :- public(run/2).
31    :- mode(run(+atom, +atom), zero_or_one).
32    :- info(run/2, [
33        comment is 'Runs the unit tests, writing the results to the specified file. Mode can be either "write" (to create a new file) or "append" (to add results to an existing file).',
34        argnames is ['File', 'Mode']]).
35
36    :- public(run/0).
37    :- mode(run, zero_or_one).
38    :- info(run/0, [
39        comment is 'Runs the unit tests, writing the results to the current output stream.']).
40
41    :- protected(setup/0).
42    :- mode(setup, zero_or_one).
43    :- info(setup/0, [
44        comment is 'Setup environment before running the test. Defaults to the goal true.']).
45
46    :- protected(test/0).
47    :- mode(test, zero_or_one).
48    :- info(test/0, [
49        comment is 'Executes the tests. By default, starts with the "succeeds" tests, followed by the "fails" tests, and than the "throws" tests.']).
50
51    :- protected(cleanup/0).
52    :- mode(cleanup, zero_or_one).
53    :- info(cleanup/0, [
54        comment is 'Cleanup environment after running the test. Defaults to the goal true.']).
55
56    % by default, no test setup is needed:
57    setup.
58
59    % by default, run all "succeeds", "fails", and "throws" tests:
60    test :-
61        test_succeeds,
62        test_fails,
63        test_throws.
64
65    test_succeeds :-
66        forall(::succeeds(Test, Goal), test_succeeds(Test, Goal)).
67
68    test_succeeds(Test, Goal) :-
69        (   catch({Goal}, _, fail) ->
70            passed_test(Test, Goal)
71        ;   failed_test(Test, Goal)
72        ).
73
74    test_fails :-
75        forall(::fails(Test, Goal), test_fail(Test, Goal)).
76
77    test_fail(Test, Goal) :-
78        (   catch(\+ {Goal}, _, fail) ->
79            passed_test(Test, Goal)
80        ;   failed_test(Test, Goal)
81        ).
82
83    test_throws :-
84        forall(::throws(Test, Goal, Error), test_throws(Test, Goal, Error)).
85
86    test_throws(Test, Goal, Error) :-
87        (   catch({Goal}, Ball, ((subsumes(Error, Ball) -> passed_test(Test, Goal); failed_test(Test, Goal)), Flag = error)) ->
88            (   var(Flag) ->
89                failed_test(Test, Goal)
90            ;   true
91            )
92        ;   failed_test(Test, Goal)
93        ).
94
95    passed_test(Test, _Goal) :-
96        self(Self),
97        write('= passed test '), writeq(Test), write(' in object '), writeq(Self), nl.
98
99    failed_test(Test, _Goal) :-
100        self(Self),
101        write('= failed test '), writeq(Test), write(' in object '), writeq(Self), nl.
102
103    % by default, no test cleanup is needed:
104    cleanup.
105
106    run(File, Mode) :-
107        open(File, Mode, Stream),
108        current_output(Output),
109        set_output(Stream),
110        ::run,
111        set_output(Output),
112        close(Stream).
113
114    run :-
115        self(Self),
116        write('% running tests from object '), writeq(Self), nl,
117        (   catch(::setup, Error, (broken(setup, Error), fail)) ->
118            (   catch(::test, Error, (broken(test, Error), Flag = error)) ->
119                do_cleanup,
120                (   var(Flag) ->
121                    write('% completed tests from object '), writeq(Self), nl
122                ;   write('% test run failed'), nl
123                )
124            ;   do_cleanup,
125                write('! test run failed for object '), writeq(Self), nl,
126                write('% test run failed'), nl
127            )
128        ;   write('! test setup failed for object '), writeq(Self), nl
129        ).
130
131    do_cleanup :-
132        self(Self),
133        (   catch(::cleanup, Error, (broken(cleanup, Error), fail)) ->
134            true
135        ;   write('! test cleanup failed for object '), writeq(Self), nl
136        ).
137
138    broken(Step, Error) :-
139        self(Self),
140        write('! broken '), write(Step), write(' for object '), writeq(Self), write(': '), write(Error), nl.
141
142:- end_object.
Note: See TracBrowser for help on using the browser.