Lab8 : Passing unit tests
The goal of this Lab is to understand the following points:
FizzBuzz¶
Create the
Lab8/directory with the following structure:
Lab8/
├── include/
│ └── fizz-buzz.h
├── source/
│ ├── fizz-buzz.cpp
│ └── main.cpp
├── tests/
│ ├── include/
│ │ └── fizz-buzz-test.h
│ └── source/
│ ├── fizz-buzz-test.cpp
│ └── main.cpp
└── makefileProject structure
This is a small coding exercise, so the project structure may seem a bit complex. The goal is to show you a typical organization for a larger project and provide you with a structure that can be reused for bigger projects.
Copy the following code into the different files.
EXECUTABLE = fizz-buzz
TEST_EXECUTABLE = fizz-buzz-tests
CXX = g++
CXXFLAGS = -std=c++17 -Iinclude
TEST_CXXFLAGS = -std=c++17 -Iinclude -Itests/include
SOURCES = $(wildcard source/*.cpp)
TEST_SOURCES = $(wildcard tests/source/*.cpp)
OBJECTS = $(patsubst source/%.cpp,build/objects/%.o,$(SOURCES))
TEST_OBJECTS = $(patsubst tests/source/%.cpp,build/tests/objects/%.o,$(TEST_SOURCES))
DEPENDENCIES = $(patsubst source/%.cpp,build/dependencies/%.d,$(SOURCES))
TEST_DEPENDENCIES = $(patsubst tests/source/%.cpp,build/tests/dependencies/%.d,$(TEST_SOURCES))
SRC_OBJECTS_NO_MAIN = $(filter-out build/objects/main.o,$(OBJECTS))
all: build/binaries/$(EXECUTABLE)
build:
mkdir -p build/objects build/dependencies build/binaries build/tests/objects build/tests/dependencies build/tests/binaries
build/binaries/$(EXECUTABLE): $(OBJECTS) | build
$(CXX) $(OBJECTS) -o build/binaries/$(EXECUTABLE)
build/tests/binaries/$(TEST_EXECUTABLE): $(SRC_OBJECTS_NO_MAIN) $(TEST_OBJECTS) | build
$(CXX) $(SRC_OBJECTS_NO_MAIN) $(TEST_OBJECTS) -o build/tests/binaries/$(TEST_EXECUTABLE)
build/objects/%.o: source/%.cpp | build
$(CXX) $(CXXFLAGS) -MMD -MF build/dependencies/$*.d -c $< -o $@
build/tests/objects/%.o: tests/source/%.cpp | build
$(CXX) $(TEST_CXXFLAGS) -MMD -MF build/tests/dependencies/$*.d -c $< -o $@
clean:
rm -rf build
run:
./build/binaries/$(EXECUTABLE)
tests: build/tests/binaries/$(TEST_EXECUTABLE)
./build/tests/binaries/$(TEST_EXECUTABLE)
.PHONY: all build clean run tests
-include $(DEPENDENCIES)
-include $(TEST_DEPENDENCIES)#include "fizz-buzz.h"
#include <string>
std::string FizzBuzz::fizzBuzz(int number) {
std::string result = "";
return result;
}#ifndef FIZZ_BUZZ_H
#define FIZZ_BUZZ_H
#include <string>
/**
* Contains only the fizzBuzz method.
*
* fizzBuzz is a method that takes a positive integer as input
* and outputs a string according to the some rules related to
* the divisibility by 2 or 7, and the presence of the digits 2 or 7.
*/
class FizzBuzz {
public:
/**
* Returns a string depending on the number.
*
* fizzBuzz returns the string according to the following rules:
* 1. if number is even, then the string contains a "Fizz";
* 2. if number is divisible by 7, then the string contains a "Buzz";
* 3. if number contains 2, then the string contains a "Fizz";
* 4. if number contains 7, then the string contains a "Buzz";
* 5. each "Fizz" or "Buzz" correspond to exactly one rule from 1. to 4.;
* 6. if none of 1. to 4. is true, then the string is the number itself;
* 7. the string must not contain more characters than necessary.
*
* @param number A positive integer.
* @return The string according to the rules above.
* @throw std::invalid_argument when number is not positive.
*/
static std::string fizzBuzz(int number);
};
/**
* @example
* \code{.cpp}
* std::cout << FizzBuzz::fizzBuzz(1); \\ Output: "1"
* std::cout << FizzBuzz::fizzBuzz(2); \\ Output: "FizzFizz"
* std::cout << FizzBuzz::fizzBuzz(7); \\ Output: "BuzzBuzz"
* std::cout << FizzBuzz::fizzBuzz(728); \\ Output: "FizzFizzBuzzBuzz"
* \endcode
*/
#endif#include "fizz-buzz.h"
#include <iostream>
int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;
std::cout << FizzBuzz::fizzBuzz(number) << std::endl;
return 0;
}#include "fizz-buzz.h"
#include "fizz-buzz-test.h"
#include <iostream>
#include <cassert>
void FizzBuzzTest::runTests() {
fizzBuzz_OddInputNonDivisibleBy7DoesNotContain2Or7_ReturnsTheSameNumber();
fizzBuzz_EvenInputNonDivisibleBy7DoesNotContain2Or7_ReturnsFizz();
fizzBuzz_EvenInputNonDivisibleBy7Contains2ButNot7_ReturnsFizzFizz();
fizzBuzz_OddInputDivisibleBy7DoesNotContain2Or7_ReturnsBuzz();
fizzBuzz_OddInputDivisibleBy7Contains7ButNot2_ReturnsBuzzBuzz();
fizzBuzz_EvenInputDivisibleBy7DoesNotContain2Or7_ReturnsFizzBuzz();
fizzBuzz_EvenInputNonDivisibleBy7Contains7ButNot2_ReturnsFizzBuzz();
fizzBuzz_OddInputDivisibleBy7Contains2ButNot7_ReturnsFizzBuzz();
fizzBuzz_OddInputNonDivisibleBy7Contains2And7_ReturnsFizzBuzz();
fizzBuzz_OddInputDivisibleBy7Contains2And7_ReturnsFizzBuzzBuzz();
fizzBuzz_EvenInputNonDivisibleBy7Contains2And7_ReturnsFizzFizzBuzz();
fizzBuzz_EvenInputDivisibleBy7Contains2ButNot7_ReturnsFizzFizzBuzz();
fizzBuzz_EvenInputDivisibleBy7Contains7ButNot2_ReturnsFizzBuzzBuzz();
fizzBuzz_EvenInputDivisibleBy7Contains2And7_ReturnsFizzFizzBuzzBuzz();
std::cout << "All tests passed\n";
}
void FizzBuzzTest::fizzBuzz_OddInputNonDivisibleBy7DoesNotContain2Or7_ReturnsTheSameNumber() {
assert(FizzBuzz::fizzBuzz(1) == "1");
assert(FizzBuzz::fizzBuzz(3) == "3");
assert(FizzBuzz::fizzBuzz(5) == "5");
assert(FizzBuzz::fizzBuzz(11) == "11");
assert(FizzBuzz::fizzBuzz(13) == "13");
assert(FizzBuzz::fizzBuzz(19) == "19");
assert(FizzBuzz::fizzBuzz(31) == "31");
assert(FizzBuzz::fizzBuzz(41) == "41");
assert(FizzBuzz::fizzBuzz(43) == "43");
assert(FizzBuzz::fizzBuzz(53) == "53");
assert(FizzBuzz::fizzBuzz(59) == "59");
std::cout << "fizzBuzz_OddInputNonDivisibleBy7DoesNotContain2Or7_ReturnsTheSameNumber passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputNonDivisibleBy7DoesNotContain2Or7_ReturnsFizz() {
assert(FizzBuzz::fizzBuzz(4) == "Fizz");
assert(FizzBuzz::fizzBuzz(6) == "Fizz");
assert(FizzBuzz::fizzBuzz(8) == "Fizz");
assert(FizzBuzz::fizzBuzz(10) == "Fizz");
assert(FizzBuzz::fizzBuzz(16) == "Fizz");
assert(FizzBuzz::fizzBuzz(18) == "Fizz");
assert(FizzBuzz::fizzBuzz(40) == "Fizz");
assert(FizzBuzz::fizzBuzz(44) == "Fizz");
assert(FizzBuzz::fizzBuzz(46) == "Fizz");
assert(FizzBuzz::fizzBuzz(48) == "Fizz");
std::cout << "fizzBuzz_EvenInputNonDivisibleBy7DoesNotContain2Or7_ReturnsFizz passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputNonDivisibleBy7Contains2ButNot7_ReturnsFizzFizz() {
assert(FizzBuzz::fizzBuzz(2) == "FizzFizz");
assert(FizzBuzz::fizzBuzz(12) == "FizzFizz");
assert(FizzBuzz::fizzBuzz(20) == "FizzFizz");
assert(FizzBuzz::fizzBuzz(24) == "FizzFizz");
assert(FizzBuzz::fizzBuzz(26) == "FizzFizz");
assert(FizzBuzz::fizzBuzz(32) == "FizzFizz");
assert(FizzBuzz::fizzBuzz(62) == "FizzFizz");
assert(FizzBuzz::fizzBuzz(82) == "FizzFizz");
std::cout << "fizzBuzz_EvenInputNonDivisibleBy7Contains2ButNot7_ReturnsFizzFizz passed\n";
}
void FizzBuzzTest::fizzBuzz_OddInputDivisibleBy7DoesNotContain2Or7_ReturnsBuzz() {
assert(FizzBuzz::fizzBuzz(35) == "Buzz");
assert(FizzBuzz::fizzBuzz(49) == "Buzz");
assert(FizzBuzz::fizzBuzz(63) == "Buzz");
assert(FizzBuzz::fizzBuzz(91) == "Buzz");
assert(FizzBuzz::fizzBuzz(105) == "Buzz");
assert(FizzBuzz::fizzBuzz(119) == "Buzz");
std::cout << "fizzBuzz_OddInputDivisibleBy7DoesNotContain2Or7_ReturnsBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_OddInputDivisibleBy7Contains7ButNot2_ReturnsBuzzBuzz() {
assert(FizzBuzz::fizzBuzz(7) == "BuzzBuzz");
assert(FizzBuzz::fizzBuzz(77) == "BuzzBuzz");
assert(FizzBuzz::fizzBuzz(147) == "BuzzBuzz");
assert(FizzBuzz::fizzBuzz(175) == "BuzzBuzz");
std::cout << "fizzBuzz_OddInputDivisibleBy7Contains7ButNot2_ReturnsBuzzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputDivisibleBy7DoesNotContain2Or7_ReturnsFizzBuzz() {
assert(FizzBuzz::fizzBuzz(14) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(56) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(84) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(98) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(140) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(154) == "FizzBuzz");
std::cout << "fizzBuzz_EvenInputDivisibleBy7DoesNotContain2Or7_ReturnsFizzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputNonDivisibleBy7Contains7ButNot2_ReturnsFizzBuzz() {
assert(FizzBuzz::fizzBuzz(74) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(76) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(78) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(170) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(174) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(176) == "FizzBuzz");
std::cout << "fizzBuzz_EvenInputNonDivisibleBy7Contains7ButNot2_ReturnsFizzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_OddInputDivisibleBy7Contains2ButNot7_ReturnsFizzBuzz() {
assert(FizzBuzz::fizzBuzz(21) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(203) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(259) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(329) == "FizzBuzz");
std::cout << "fizzBuzz_OddInputDivisibleBy7Contains2ButNot7_ReturnsFizzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_OddInputNonDivisibleBy7Contains2And7_ReturnsFizzBuzz() {
assert(FizzBuzz::fizzBuzz(27) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(127) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(527) == "FizzBuzz");
assert(FizzBuzz::fizzBuzz(927) == "FizzBuzz");
std::cout << "fizzBuzz_OddInputNonDivisibleBy7Contains2And7_ReturnsFizzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_OddInputDivisibleBy7Contains2And7_ReturnsFizzBuzzBuzz() {
assert(FizzBuzz::fizzBuzz(217) == "FizzBuzzBuzz");
assert(FizzBuzz::fizzBuzz(273) == "FizzBuzzBuzz");
assert(FizzBuzz::fizzBuzz(427) == "FizzBuzzBuzz");
assert(FizzBuzz::fizzBuzz(721) == "FizzBuzzBuzz");
std::cout << "fizzBuzz_OddInputDivisibleBy7Contains2And7_ReturnsFizzBuzzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputNonDivisibleBy7Contains2And7_ReturnsFizzFizzBuzz() {
assert(FizzBuzz::fizzBuzz(72) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(272) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(274) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(726) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(872) == "FizzFizzBuzz");
std::cout << "fizzBuzz_EvenInputNonDivisibleBy7Contains2And7_ReturnsFizzFizzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputDivisibleBy7Contains2ButNot7_ReturnsFizzFizzBuzz() {
assert(FizzBuzz::fizzBuzz(28) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(42) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(112) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(126) == "FizzFizzBuzz");
assert(FizzBuzz::fizzBuzz(182) == "FizzFizzBuzz");
std::cout << "fizzBuzz_EvenInputDivisibleBy7Contains2ButNot7_ReturnsFizzFizzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputDivisibleBy7Contains7ButNot2_ReturnsFizzBuzzBuzz() {
assert(FizzBuzz::fizzBuzz(70) == "FizzBuzzBuzz");
assert(FizzBuzz::fizzBuzz(378) == "FizzBuzzBuzz");
assert(FizzBuzz::fizzBuzz(476) == "FizzBuzzBuzz");
std::cout << "fizzBuzz_EvenInputDivisibleBy7Contains7ButNot2_ReturnsFizzBuzzBuzz passed\n";
}
void FizzBuzzTest::fizzBuzz_EvenInputDivisibleBy7Contains2And7_ReturnsFizzFizzBuzzBuzz() {
assert(FizzBuzz::fizzBuzz(728) == "FizzFizzBuzzBuzz");
assert(FizzBuzz::fizzBuzz(2716) == "FizzFizzBuzzBuzz");
std::cout << "fizzBuzz_EvenInputDivisibleBy7Contains2And7_ReturnsFizzFizzBuzzBuzz passed\n";
}#ifndef FIZZ_BUZZ_TEST_H
#define FIZZ_BUZZ_TEST_H
class FizzBuzzTest {
public:
static void runTests();
private:
static void fizzBuzz_OddInputNonDivisibleBy7DoesNotContain2Or7_ReturnsTheSameNumber();
static void fizzBuzz_EvenInputNonDivisibleBy7DoesNotContain2Or7_ReturnsFizz();
static void fizzBuzz_EvenInputNonDivisibleBy7Contains2ButNot7_ReturnsFizzFizz();
static void fizzBuzz_OddInputDivisibleBy7DoesNotContain2Or7_ReturnsBuzz();
static void fizzBuzz_OddInputDivisibleBy7Contains7ButNot2_ReturnsBuzzBuzz();
static void fizzBuzz_EvenInputDivisibleBy7DoesNotContain2Or7_ReturnsFizzBuzz();
static void fizzBuzz_EvenInputNonDivisibleBy7Contains7ButNot2_ReturnsFizzBuzz();
static void fizzBuzz_OddInputDivisibleBy7Contains2ButNot7_ReturnsFizzBuzz();
static void fizzBuzz_OddInputNonDivisibleBy7Contains2And7_ReturnsFizzBuzz();
static void fizzBuzz_OddInputDivisibleBy7Contains2And7_ReturnsFizzBuzzBuzz();
static void fizzBuzz_EvenInputNonDivisibleBy7Contains2And7_ReturnsFizzFizzBuzz();
static void fizzBuzz_EvenInputDivisibleBy7Contains2ButNot7_ReturnsFizzFizzBuzz();
static void fizzBuzz_EvenInputDivisibleBy7Contains7ButNot2_ReturnsFizzBuzzBuzz();
static void fizzBuzz_EvenInputDivisibleBy7Contains2And7_ReturnsFizzFizzBuzzBuzz();
};
#endif#include "fizz-buzz-test.h"
int main() {
FizzBuzzTest::runTests();
return 0;
}Read the documentation of the
FizzBuzzclass as well as the tests.Implement the
fizzBuzzfunction infizz-buzz.cppso that all tests pass.
Hints
std::to_string(number)returns the string representation ofnumber(for example,std::to_string(3)returns"3").a % breturns the remainder of the division ofabyb(for example,3 % 2returns1).bigString.find(smallString) != std::string::nposreturns true ifbigStringcontainssmallString, otherwise false."3" + "3"returns"33".
Go back to the objectives and check off the points you have mastered. Review the points you do not yet fully understand. Ask your instructor if necessary.