Test the Car
Class
Now we'll start testing some of the code you've written! There are two key aspects to our approach to testing: running tests using the CS 70 testing library, and using Valgrind to detect memory errors.
The testtrain
Program
In this part of the assignment, you are going to test out your Car
class using the testtrain
program. (For this assignment, we gave you very little code to start with, but we did provide testtrain.cpp
!)
Take a look at the testtrain.cpp
file. There are several test functions that increase in complexity.
The runTests()
function runs all the tests. In the provided version of the code, all the tests are commented out. In this step, you will uncomment each of the Car
tests one by one to make sure your code does what it is supposed to do.
main()
takes in a command-line argument which can be:
T
— Run a predefined set of tests on theCar
andTrain
classes.B
— Run an interactive session using aBASIC
train.S
— Run an interactive session using aSMART
train.
We'll be using the T
option at the moment.
All the testing functions use the CS 70 testing library. In later assignments, you'll have to write your own tests using this library, but in this assignment you just have to use the tests and understand what they do.
Running Programs Using Valgrind
You will also learn about a tool called Valgrind, which runs your program in a special way that allows it to detect three kinds of common errors:
- Reading from memory that you haven't properly initialized.
- Reading or writing memory that is way out of bounds.
- Failing to use the heap properly (especially memory leaks).
Valgrind is not a panacea. It does not detect all errors or all kinds of undefined behavior, but it is still a very useful way to debug your program.
Your Tasks
Reason About Expected Output in Test Cases
Open testtrain.cpp
and look at the test cases that involve the Car
class (the section of code labeled Car Testing Functions
in comments).
Many of the tests output a Car
and check that it looks as expected. The tests do not explain why the output is correct, however. You'll have to reason that out for yourself.
Test the Car
Class's Constructor and Destructor
The function testDeclareCar()
declares a Car
and checks some of its informational functions. It causes the Car
class's constructor and destructor to be called.
-
Uncomment the line
testDeclareCar();
inrunTests()
. -
Compile using
make
(orcs70-make
if you prefer) -
See if the
testtrain
program detects any problems by running it in the normal way:./testtrain T
-
Also run your code using Valgrind to see if it can detect any additional errors, by running
valgrind --leak-check=full ./testtrain T
-
If you found any errors, fix them and go back to Step 2.
Test Car
's printToStream
Functionality
Now is a good time to make sure you can print out a Car
object before we start doing anything more interesting with it.
-
Uncomment
testOutputEmptyCar();
inrunTests()
. -
Recompile, rerun normally and with Valgrind as above, and fix any errors.
When run without valgrind
, the output of the test program is easy to see. Here's a sample successful output:
01 test declare car passed!
02 test output empty car passed!
all tests passed! Summary of affirmations:
----
Fails / Total Issue
0 / 3 [01 test declare car]
0 / 1 [02 test output empty car]
But when you run with valgrind
, the output of your program mixed in with Valgrind's output, and you may have to scroll to find the test results.
==79== Memcheck, a memory error detector
==79== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==79== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==79== Command: ./testtrain T
==79==
01 test declare car passed!
02 test output empty car passed!
all tests passed! Summary of affirmations:
----
Fails / Total Issue
0 / 3 [01 test declare car]
0 / 1 [02 test output empty car]
==79==
==79== HEAP SUMMARY:
==79== in use at exit: 0 bytes in 0 blocks
==79== total heap usage: 35 allocs, 35 frees, 74,104 bytes allocated
==79==
==79== All heap blocks were freed -- no leaks are possible
==79==
==79== For lists of detected and suppressed errors, rerun with: -s
==79== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
In both cases, you can see that all tests passed.
Make Sure You Can Run the Remaining Car
Tests
There are several more test functions for Car
s. They do various things, such as add packages to cars; add and remove packages; add and print then remove and print; and so on. Make sure your code does the right thing for each of the tests by uncommenting them one at a time, compiling, and running them.
Optional: You can write more tests!
There is no guarantee that our set of tests will find all possible correctness or memory errors in your code. We always suggest that you come up with tests of your own if you think it will help you'll debug your program. We won’t specifically evaluate your test code (this time!), but we will check the correctness of your code with our own extensive suite of tests—and correctness certainly factors into your grade!
I'll add tests to check undefined behavior!
NO! Never break the rules to try to test undefined behavior. Your testing code always has to follow the rules. If you're not allowed to do something, your testing code can't do that thing.
Do we get extra credit for writing extra tests?
Sorry, no. But getting some practice will help you in future assignments.
Guess what I'm not doing. Meh.
(When logged in, completion status appears here.)