$24
Information
In-class labs are meant to introduce you to a new topic and provide some practice with that new topic.
Topics: Designing and implementing unit tests
Solo work: Labs should be worked on by each individual student, though asking others for help is permitted. Do not copy code from other sources, and do not give your code to other students. Students who commit or aid in plagiarism will receive a 0% on the assignment and be reported.
Building and running: If you are using Visual Studio, make sure to run with debugging. Do not run without debugging!
Using the debugger will help you nd errors.
To prevent a program exit, use this before return 0;
cin.ignore(); cin.get();
Turn in: Once you're ready to turn in your code, prepare the les by
doing the following: (1) Make a copy of your project folder and name it
LASTNAME-FIRSTNAME-LABNAME. (Example: HOPPER-GRACE-LAB-UNIT-TESTS)
Make sure that all source les (.cpp, .hpp, and/or .h les) and the Makefile les are all present. (3) Remove all Visual Studio les - I only want the source les and Make les. (4) Zip your project folder as LASTNAME-FIRSTNAME-LABNAME.zip
Never turn in Visual Studio les!
Starter les: Download from GitHub.
Grading: Grading is based on completion, if the program functions as intended, and absense of errors. Programs that don't build will receive 0%. Besides build errors, runtime errors, logic errors, memory leaks, and ugly code will reduce your score.
Contents
1.1
About . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.2
Setting up the project . . . . . . . . . . . . . . . . . . . . . .
3
1.2.1
Running the tests . . . . . . . . . . . . . . . . . . . . .
5
1.3
Lab speci cations . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.3.1
Function 1: SumThree . . . . . . . . . . . . . . . . . .
5
1.3.2
Function 2: SumArray . . . . . . . . . . . . . . . . . .
7
1.3.3
Function 3: IsOverdrawn . . . . . . . . . . . . . . . . .
8
1.3.4
Function 4: GetLength . . . . . . . . . . . . . . . . . .
9
1.1 About
Unit tests are small tests meant to validate functions. As functions, at a basic level, simply take inputs and result in some output, we can generally come up with a list of expected outputs, given some inputs.
For example, if we have a function like this:
int ReturnOneGreater( int n );
and we know that the function is supposed to return n + 1 for any n passed in, we can then build test cases like this:
Input:
1
Output: 2
Input:
-1
Output: 0
Input: -5Output: -4
And we can validate the function by testing each of these scenarios. If, for some reason, the actual output we receive di ers from the expected output, this suggests that something is wrong with the function.
Unit tests come in handy as you're building up large projects. As you implement one feature at a time, you can also build tests along with those features. Then, after each subsequent feature you add, you can run all your tests to ensure that everything still works - that you didn't inadvertantly break anything.
1.2 Setting up the project
Download the starter zip le, LAB-UNIT-TESTS.zip, o GitHub. This zip le contains the following:
function1.hpp function2.hpp function3.hpp function4.hpp
tester program.cpp
Makefile
All of these source les belong in one project and are not separate pro-grams.
For this lab, there are already several functions included. Each of these functions have logic errors. You will be writing unit tests to test out the expected functionality, and to locate where the error is, then x it.
Function stubs are also already provided - you just have to ll them in. The program is built so that it should launch and automatically run the tests without you having to do any coding outside of the tests themselves.
Do not modify main() or anything in testing program.cpp!
Warning!
Common error!
It is very common for students who are new to the concept of unit tests to make the following mistake:
REWRITING THE TEST TO PASS,
INSTEAD OF WRITING THE TEST TO BE CORRECT.
The tests you write should be logically sound, and if the tests fail, you should be investigating the function being tested to nd something to x. You should NOT, however, rewrite your test so that it passes - this means your function is still incorrect and the test is incorrect, too.
Example: Let's say you have a function that takes three inputs: a, b, and c. The result should be a + b + c. You write a test that sets a = 2, b = 3, and c = 4. The expected output is 9, but instead the function returns 24. Something's wrong!
INCORRECT FIX: You change the test so that the expected output is 24.
CORRECT FIX: You investigate the function that should be adding the values, nd that its math is wrong, and x the math.
1.2.1 Running the tests
When you run the program, it will have a menu with options to test each function:
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
** TESTER **
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1. Test AddThree
2. Test I s O v e r d r a w n
3. Test T r a n s l a t e W o r d
4. Test Ge tL en gt h
5. Quit
Test which function ?
When you select one of the functions, it will run the tests and display whether each test passed or failed.
* * * * * * * * * * * * T e s t _ A d d T h r e e * * * * * * * * * * * *
T e s t _ A d d T h r e e : Test 1 passed !
T e s t _ A d d T h r e e : Test 2 FAILED !
T e s t _ A d d T h r e e : Test 3 FAILED !
Based on which test failed, you can look at the inputs and outputs to help you gure out where the logic error is at in these functions.
1.3 Lab speci cations
1.3.1 Function 1: SumThree
Each of these .hpp les contain a function to be tested and a test func-tion with one test already written.
The function for the rst le is:
1 int SumThree ( int a , int b , int c )
2 {
3 return a + b + b ;
4 }
You can probably already see the logic error here, but don't x it yet; you will x it after you write all the tests.
Inside the Test SumThree function, there is one test already written:
CS 250
Lab : Unit Tests
1
/* TEST
1
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2
input1
=
1; input2 = 1; input3 =
1;
3
e x p e c t e d O u t p u t = 3;
4
5
a c t u a l O u t p u t = SumThree ( input1 ,
input2 , input3 ) ;
6
if ( a c t u a l O u t p u t == e x p e c t e d O u t p u t )
7
{
8
cout << " T e s t _ A d d T h r e e : Test 1 passed ! " << endl <<
endl ;
}
10
else
11
{
12
cout << " T e s t _ A d d T h r e e : Test 1 FAILED ! \ n \ t "
13
// ... more info ..
}
This test has the following data:
Test #
Input 1
Input 2
Input 3
Expected output
1
1
1
1
3
2
3
But, a single test isn't enough to fully cover this function, we need more. Build out the table so that there are at least three total test cases before continuing.
Before programming in your tests, ask yourself the following:
Do your test cases cover both positive and negative input values? Do your test cases cover both positive and negative output values? Do your test cases have di erent values for inputs 1, 2, and 3?
Make sure your test cases are varied enough; your new tests shouldn't just be \1 + 1 + 1 = 3", \2 + 2 + 2 = 6", \3 + 3 + 3 = 9", and so on...
Once your test cases are done, it's time to program them in. There are two additional tests in the Test SumThree function. To set them up, simply replace the values of the input and expectedOutput variables:
CS 250,
Lab : Unit Tests
1
input1
=
0;
//
change
me
2
input2
=
0;
//
change
me
3
input3
=
0;
//
change
me
4
e x p e c t e d O u t p u t = -1;
//
change
me
After you've updated these, run the tests for the SumThree function again. Your tests should fail because the logic error hasn't been xed yet. While the error is pretty obvious for this function, logic errors are not always obvious. This is where unit tests really come in handy.
Fix the logic error in the function, re-run the tests, and make sure every-thing passes. Once it does, move on to the next le.
1.3.2 Function 2: SumArray
1
int SumArray (
int
arr [] ,
int size )
2
{
3
for ( int
i
=
0; i <=
size ; i ++ )
4
{
5
int
sum
=
0;
6
sum
+=
arr [ i ];
}
8
return sum ;
9
}
Again, each of these functions has a logic error. Plan out your test cases,
then implement them, test, and try to locate the error and x it.
Function description:
SumArray function This function should take an array of inte-
gers, arr[], as well as the amount of items stored in that array,
size.
The return value is the sum of all of the elements in the array.
Test cases:
Test #
Input array
Expected output
1
f 1, 2, 3, 4 g
10
2
3
1.3.3 Function 3: IsOverdrawn
bool I s O v e r d r a w n ( float balance )
2 {
if ( balance <= 0 )
4 {
5 return true ;
6 }
7 else
8 {
9 return false ;
10 }
11 }
Function description:
IsOverdrawn function This function should take a oat, balance, as the input.
The function will return true if the account is overdrawn and false if the account is not overdrawn. An account is only over-drawn if the account balance is negative.
Test cases:
Test #
Input
Expected output
1
0
false
2
3
1.3.4 Function 4: GetLength
int Ge tL en gt h ( string word )
2 {
int length = 3;
4 word . size () ;
5 return length ;
6 }
Function description:
IsOverdrawn function This function should take a string, word, as the input.
The function will return the amount of letters in the word given.
Test cases:
Test #
Input
Expected output
1
\cat"
3
2
3