Skip to content

Commit

Permalink
test: add unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
wgy8283335 committed Mar 1, 2024
1 parent 25cc377 commit a2726e4
Show file tree
Hide file tree
Showing 14 changed files with 98 additions and 74 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ build
.vscode
cpm_modules
.DS_Store
.cache
.cache
compile_commands.json
.cpm_cache
make_compile_commands_json.sh
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ Additional arguments can be passed to the analyzers by setting the `CLANG_TIDY_A
Ccache can be enabled by configuring with `-DUSE_CCACHE=<ON | OFF>`.

## FAQ
> How to set cpm cache to avoid downloading third party package everytime?
export CPM_SOURCE_CACHE=$HOME/VSProjects/C++Learning/ModernCppStarter/.cpm_cache

> What is .github/workflows used for?
The directory contains several files defining CI steps in github.
Expand Down
12 changes: 9 additions & 3 deletions include/effective_c++/Cave.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@ namespace effective {
Cave& operator=(Cave&& right) = delete;
virtual ~Cave() = default;

/**
* @brief Construct the Cave object with address.
* @param name The address of the Home.
*/
explicit Cave(std::string address);

private:
virtual int doHealthValue() const override;
virtual void doDraw(int color) const override;
virtual void onTick() const override;
virtual std::string doHealthValue() const override;
virtual std::string doDraw(int color) const override;
virtual std::string onTick() const override;
Lock key; // This key is used by animal, only one animal could stay in the Cave at one time.
};
} // namespace effective
Expand Down
5 changes: 3 additions & 2 deletions include/effective_c++/Clock.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#ifndef EFFECTIVE_CLOCK_H_
# define EFFECTIVE_CLOCK_H_
# include <string>

namespace effective {
/**
Expand All @@ -11,11 +12,11 @@ namespace effective {
public:
Clock() = default;
explicit Clock(int tickFrequency);
virtual void tick() const;
virtual std::string tick() const;
virtual void stop();

private:
virtual void onTick() const;
virtual std::string onTick() const;
int tick_frequency;
bool is_running{true};
};
Expand Down
18 changes: 9 additions & 9 deletions include/effective_c++/Home.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ namespace effective {
virtual ~Home();

/**
* @brief Construct the Home object with name and weight.
* @param name The name of the Home.
* @brief Construct the Home object with address.
* @param name The address of the Home.
*/
explicit Home(std::string address); //>此处使用explicit防止单参构造函数用于隐式类型转换

Expand All @@ -41,22 +41,22 @@ namespace effective {
//> healthValue称为doHealthValue的包装器。
//> 除了用模板方法可以替代virtual函数。也可以采用策略模式+函数指针/函数对象,来实现。
//> 具体参考Effective C++ Item35.
int healthValue() const;
std::string healthValue() const;
//> 这里定义draw为public non-virtual带有默认参数,因为带有默认参数的函数不适合定义为虚函数
//> 所以这里定义doDraw()为virtual,它在draw()中被调用。让派生类可以重写doDraw()。
//> 这就是Effective C++ Item37中提倡的行为。
void draw(int color = 1) const;
std::string draw(int color = 1) const;
// boardcast the address to the habitant.
void boardcastAddress() const;
std::string boardcastAddress() const;

protected:
std::string address_;

private:
//> doHealthValue是private级别,派生类访问不到,但是派生类可以重写属于自己的函数。
//> healtValue根据派生类对象调用对应的doHealthValue()函数。
virtual int doHealthValue() const;
virtual void doDraw(int color) const = 0;
virtual std::string doHealthValue() const;
virtual std::string doDraw(int color) const = 0;
//> 通过私有继承方式重写onTick,可以防止Home的调用者调用onTick。
//> 且私有继承表明 Home is not a Clock。
//> 不过这种写法虽然可以防止Home派生类调用onTick(),但无法防止Home的派生类重写onTick。
Expand All @@ -65,13 +65,13 @@ namespace effective {
//> 私有成员函数和成员变量,都是用//进行注释。
// This function is responsible for sending the location of the broadcaster at regular
// intervals to help the animal to find its way home.
virtual void onTick() const;
virtual std::string onTick() const;
//> 当只想继承并重写某个虚函数的时候,可以用一下方法:
//> 定义转交函数,私有继承+重写的方式,可以选择只继承Clock的tick()函数。
//> Clock::stop()私有继承体系下不会被暴露出去。
// Override tick from Clock. The class only need tick() to support the implementation of
// boardcastAddress fucntion.
virtual void tick() const;
virtual std::string tick() const;
};
} // namespace effective
#endif // EFFECTIVE_HOME_H_
6 changes: 3 additions & 3 deletions include/effective_c++/Nest.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ namespace effective {
virtual ~Nest() = default;

private:
virtual int doHealthValue() const override;
virtual void doDraw(int color) const override;
virtual void onTick() const override;
virtual std::string doHealthValue() const override;
virtual std::string doDraw(int color) const override;
virtual std::string onTick() const override;

Lock key; // This key is used by bird, only one bird could stay in the nest at one time.
};
Expand Down
17 changes: 10 additions & 7 deletions source/effective_c++/Clock.cc
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
#include "effective_c++/clock.h"

#include <iostream>
#include <thread>

using std::cout;
using std::string;
using namespace effective;

Clock::Clock(int tickFrequency) : tick_frequency(tickFrequency) {}

void Clock::onTick() const { cout << "Only tick."; }
string Clock::onTick() const { return "tick "; }

void Clock::tick() const {
string Clock::tick() const {
using std::this_thread::sleep_for;
cout << "Tick begin";
while (is_running) {
onTick();
auto num = 0;
string result = "Tick begin ";
while (is_running && (num < 10)) {
num++;
result += onTick();
// sleep for 1000 ms.
sleep_for(std::chrono::milliseconds(1000 / tick_frequency));
}
result += "end.";
return result;
}

void Clock::stop() { is_running = false; }
33 changes: 16 additions & 17 deletions source/effective_c++/Home.cc
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
#include "effective_c++/home.h"

#include <iostream>

//> 不要导入整个命名空间std,因为会有符号名冲突。导入具体的符号可以将冲突范围最小化。
using std::cout;
using std::string;
using namespace effective;

Home::Home(string address) : Clock(1), address_(address) {}

Home::~Home() {}

int Home::healthValue() const {
cout << "do something before doHealthValue().";
int retVal = doHealthValue();
cout << "do something after doHealthValue().";
return retVal;
string Home::healthValue() const {
string before = "before ";
string record = doHealthValue();
string after = " after.";
return before + record + after;
}

void Home::draw(int color) const { doDraw(color); }
string Home::draw(int color) const { return doDraw(color); }

void Home::boardcastAddress() const { tick(); }
string Home::boardcastAddress() const { return tick(); }

int Home::doHealthValue() const { return 1; }
string Home::doHealthValue() const { return "check health of full house"; }

void Home::doDraw(int color) const {
string Home::doDraw(int color) const {
if (color == 1) {
cout << "let paint the house as Red";
return "let paint the house as Red";
}
return "bad color, can not paint.";
}

void Home::onTick() const { cout << "My home address is : " + address_; }
string Home::onTick() const { return "My home address is : " + address_; }

void Home::tick() const {
cout << "This from home";
Clock::tick();
string Home::tick() const {
string result = "This from home begin send address ";
result += Clock::tick();
return result;
}
12 changes: 5 additions & 7 deletions source/effective_c++/Nest.cc
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#include "effective_c++/nest.h"

#include <iostream>

using std::cout;
using namespace effective;

int Nest::doHealthValue() const { return 2; }
std::string Nest::doHealthValue() const { return "check health of full Nest"; }

void Nest::doDraw(int color) const {
std::string Nest::doDraw(int color) const {
if (color == 2) {
cout << "let paint the house as Blue";
return "let paint the house as Blue";
}
return "bad color, can not paint.";
}

void Nest::onTick() const { cout << "My nest address is : " + address_; }
std::string Nest::onTick() const { return "My nest address is : " + address_; }
17 changes: 17 additions & 0 deletions source/effective_c++/cave.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "effective_c++/cave.h"

using std::string;
using namespace effective;

Cave::Cave(string address) : Home(address) {}

string Cave::doHealthValue() const { return "check health of full Cave"; }

string Cave::doDraw(int color) const {
if (color == 3) {
return "let paint the house as Brown";
}
return "bad color, can not paint.";
}

string Cave::onTick() const { return "My cave address is : " + address_; }
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)

project(GreeterTests LANGUAGES CXX)
# this command for clangd to generate compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# ---- Options ----

Expand Down
33 changes: 13 additions & 20 deletions test/source/cave_test.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
#include <doctest/doctest.h>
#include <greeter/greeter.h>
#include <greeter/version.h>

#include <string>

TEST_CASE("Greeter") {
using namespace greeter;

Greeter greeter("Tests");

CHECK(greeter.greet(LanguageCode::EN) == "Hello, Tests!");
CHECK(greeter.greet(LanguageCode::DE) == "Hallo Tests!");
CHECK(greeter.greet(LanguageCode::ES) == "¡Hola Tests!");
CHECK(greeter.greet(LanguageCode::FR) == "Bonjour Tests!");
}

TEST_CASE("Greeter version") {
static_assert(std::string_view(GREETER_VERSION) == std::string_view("1.0"));
CHECK(std::string(GREETER_VERSION) == std::string("1.0"));
#include "effective_c++/cave.h"

#include "doctest/doctest.h"

TEST_CASE("Cave") {
using namespace effective;
auto one_cave = Cave("ParaMountain");
one_cave.boardcastAddress();
CHECK(one_cave.draw(3) == "let paint the house as Brown");
CHECK(one_cave.healthValue() == "before check health of full Cave after.");
CHECK(one_cave.GetAddress("decorate ") == "decorate ParaMountain");
CHECK(one_cave.GetAddress() == "ParaMountain");
CHECK(one_cave.boardcastAddress() == "This from home begin send address Tick begin My cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainMy cave address is : ParaMountainend.");
}
7 changes: 3 additions & 4 deletions test/source/greeter.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include <doctest/doctest.h>
#include <greeter/greeter.h>
#include <greeter/version.h>
#include "greeter/greeter.h"

#include <string>
#include "doctest/doctest.h"
#include "greeter/version.h"

TEST_CASE("Greeter") {
using namespace greeter;
Expand Down
2 changes: 1 addition & 1 deletion test/source/main.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

#include <doctest/doctest.h>
#include "doctest/doctest.h"

0 comments on commit a2726e4

Please sign in to comment.