Fishtank
|
It's time to write some tests! For this assignment, you will design and implement a set of unit tests for some code we have written.
Our code implements an API for state tracking and rendering of a virtual "fishtank" which, like a real fishtank, contains fish, rocks, and other things that you can see but not interact with. (This is inspired by an older assignment from Tufts' CS 11.) The API assumes that these objects will be drawn to a terminal and so represents each one as an ASCII art string. For example, a fish might look like this:
The things in the tank (all of which we call "fish", for simplicity) can move on their own, meaning the state of the tank changes over time. The exact rate of change is not fixed; instead, the API operates in "ticks", an abstract unit of time which represents a single movement of each object.
The C++ API for the fishtank consists of several classes, which are declared across several header files. You can find documentation for each class in the "Classes" dropdown of this website, which has been generated using a tool called Doxygen. (See README.md
for the source code of this page.)
As you can see, we have a Fish class which represents a single object in the tank that knows its own appearance, position, and speed. We also have a Tank class which represents a tank containing an arbitrary number of fish that knows how to render all of those fish onto a virtual canvas (a subclass of Screen, some of which can render themselves as a multi-line string) of a given width and height.
.cpp
files yet. Looking at the header and Markdown files is fine. You will look at the other source files later.fish-test.cpp
, etc) that you will later fill in. Build the project. Test that the project builds and runs as-is (./build/fishtank-tests
). Zero tests should run.main.cpp
. This client creates a tank with some fish, rocks, and seaweed, then calls the Tank::tick, and Tank::draw functions to move the fish and draw them to the screen, respectively. The latter is accomplished with the help of a CursesScreen object, which is not part of the API you need to test, since it's specific to our demo app.Your work, however, will not involve our demonstration client at all. Instead, you will be writing unit tests that call into the API directly via the classes shown above. Instead of CursesScreen, you'll use StringScreen, which returns the rendered tank as a string that can be easily inspected by automated tests.
-test.cpp
file. You might find the documentation for utest and the example test below helpful. Note that you only need to write unit tests for this assignment. You need not write any integration tests, as UTest is not very well suited to writing integration tests..cpp
files. What corner cases did you miss? Reflect on that. Write some more unit tests.Here is a sample test template to get you started:
and another one based on the Fish class:
All the tests in a file should be part of the same test case, meaning the first argument to each UTEST macro (SampleTestSuite
, in this example) should match. It's conventional to name the test case after the class being tested, for example TankTests
or FishTests
.
You should expect to write many tests for each class. Although the code is relatively simple, there's still a lot that could go wrong, and we'll be running your unit tests to make sure they catch a variety of issues (see next section). The files you provide will likely contain several hundred lines of code in total, although some of this will be UTEST()
macros and setup code that's common to multiple tests.
To write tests for functions returning std::string
, you must compare the underlying C string (by calling .c_str()
) using EXPECT_STREQ
or ASSERT_STREQ
. This is a limitation (for now! Max is working on submitting a patch) of the underlying UTest library.
Once you submit your unit tests, we will run them against a variety of broken implementations that we (the course staff) have come up with. These implementations are not specifically designed to thwart unit tests; we came up with them before seeing your submissions, and all the errors they introduce might reasonably be made in the real world (so none of them fail only when the screen width is exactly 54, for example). We are keeping these implementations a secret, so the only way you'll catch a majority of them is if you write comprehensive tests for the behavior our API documentation guarantees.
50% of your grade for this assignment will be based purely on these automated test results, although we reserve the right to curve up this portion of the grade for everyone if it's lower than we expect. The other 50% of your grade will be based on subjective evaluation of the code quality and adherence to best practices of the tests you write.
Submit all of your *-test.cpp
files on Gradescope.
This is not necessary to complete the assignment. It is half a reminder to ourselves for how to build the documentation, and half a curiosity for you.
mkdir -p build/
doxygen
build/doxygen/html/
.cp -r build/doxygen/html/ -T ../../isdt/assignments/08-cor-constructive