Skip to content

Notes from chat about text adventure project #46

@simonharris

Description

@simonharris

Since the library is an xUnit-style tool providing general assertions like assert_true/1 and assert_equals/2, you need to exercise how it handles Prolog’s unique execution model—specifically backtracking and the side effects of the dynamic database.

Here are three specific ways to use the text-based game to stress-test your xUnit predicates:

Testing "Nondeterministic Success"

In Prolog, a predicate might succeed multiple times with different bindings. A standard assert_true(search(room, Item)) only tells you if the predicate succeeded once.
The Project Goal: Implement a search/2 predicate where one room contains multiple hidden items.
The Test Challenge: Use your library to verify that all items are discoverable. You would likely write a test using findall/3 or forall/2:

test_search_finds_everything :-
    findall(I, search(attic, I), FoundItems),
    assert_equals([dusty_key, old_map, spider], FoundItems).

What this exercises: Can your library handle the list-processing results of findall and provide a useful diff if the list order is wrong or an item is missing?

Testing "State Persistence & Cleanup"

Text games rely on assertz and retract. This is the "nightmare scenario" for unit testing because tests can easily pollute each other.

The Project Goal: Implement a take(Item) predicate that changes the state from at(Item, Room) to has(Player, Item).
The Test Challenge: Ensure that a test for "taking the sword" doesn't leave the sword in the player's inventory for the "taking the shield" test.

What this exercises: This will force you to implement (or test) Setup/Teardown logic in your library. Does your library provide a way to wrap a test in a setup (initializing the map) and a cleanup (clearing the dynamic database), perhaps using setup_call_cleanup/3?

Testing "Logical Impossibility" (The Failure Case)

In xUnit, we often test that an error is thrown. In Prolog, we often test that a predicate simply fails (the "Closed World Assumption").

The Project Goal: Implement movement constraints (e.g., you cannot go(north) if there is a wall(north)).
The Test Challenge: You need a way to assert that a player cannot move through a wall.

test_cannot_walk_through_walls :-
    % Assuming the player is at a boundary
    \+ move(north), % Standard Prolog check
    assert_false(move(north)). % Using your library's equivalent

What this exercises: Does your library have an assert_false/1 or assert_fail/1? If move(north) incorrectly succeeds, does your library capture why (i.e., what the unexpected binding was)?

Testing "Multiple Paths"/the "Backtracking" Test

The Project Goal: A can_reach_exit(Path) predicate that finds a path from the start to the end of a dungeon.
The Test Challenge: Use your library to verify that the "shortest path" is exactly length X.
What this exercises: This tests your assert_equals/2 against complex terms (lists of atoms). If the test fails, does your library print a readable comparison of the two paths?

In short: The game provides the mutating state and logical branches that standard xUnit libraries for functional or OOP languages never have to deal with. It will quickly show you if your library is "Prolog-aware" enough to handle backtracking and database resets.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions