[PR] Implement tests for GradeCalculator and FinalGradeDeterminator, add documentation for aformentioned nodes #4

Merged
vincent merged 8 commits from 1-grade-generator/cijfer-determinator-calculator into 1-grade-generator/master 2025-10-07 10:07:12 +02:00
2 changed files with 117 additions and 0 deletions
Showing only changes of commit 887e99c909 - Show all commits

View File

@@ -127,6 +127,20 @@ if(BUILD_TESTING)
target_link_libraries(${PROJECT_NAME}_test_exam_result_generator target_link_libraries(${PROJECT_NAME}_test_exam_result_generator
pqxx pq tomlplusplus::tomlplusplus pqxx pq tomlplusplus::tomlplusplus
) )
# Add gtest for GradeCalculator
ament_add_gtest(${PROJECT_NAME}_test_grade_calculator
test/GradeCalculator.test.cpp
src/grade_calculator/nodes/GradeCalculator.cpp
)
target_include_directories(${PROJECT_NAME}_test_grade_calculator PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/grade_calculator
)
ament_target_dependencies(${PROJECT_NAME}_test_grade_calculator
rclcpp
g2_2025_interfaces
)
endif() endif()
ament_package() ament_package()

View File

@@ -0,0 +1,103 @@
#include <gtest/gtest.h>
#include <rclcpp/rclcpp.hpp>
#include <thread>
#include <g2_2025_interfaces/srv/exams.hpp>
#include "grade_calculator/nodes/GradeCalculator.hpp"
using namespace std::chrono_literals;
using assignments::one::grade_calculator::GradeCalculator;
class GradeCalculatorTest : public ::testing::Test
{
vincent marked this conversation as resolved Outdated

Formatting (check whole document)

Formatting (check whole document)
protected:
static void SetUpTestSuite() {
int argc = 0;
char **argv = nullptr;
rclcpp::init(argc, argv);
}
static void TearDownTestSuite() {
rclcpp::shutdown();
}
void SetUp() override
{
// Start GradeCalculator node
grade_calculator_node_ = std::make_shared<GradeCalculator>();
executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
executor_->add_node(grade_calculator_node_);
// Spin in background thread
spin_thread_ = std::thread([this]() {
executor_->spin();
});
// Create client node
client_node_ = rclcpp::Node::make_shared("grade_calculator_test_client");
client_ = client_node_->create_client<g2_2025_interfaces::srv::Exams>("grade_calculator_service");
}
void TearDown() override
{
executor_->cancel();
if (spin_thread_.joinable()) {
spin_thread_.join();
}
grade_calculator_node_.reset();
client_.reset();
client_node_.reset();
}
int call_service(const std::string &name, const std::vector<int> &grades)
{
if (!client_->wait_for_service(5s)) {
throw std::runtime_error("Service not available");
}
auto request = std::make_shared<g2_2025_interfaces::srv::Exams::Request>();
request->student_name = name;
request->exam_grades = grades;
auto future = client_->async_send_request(request);
if (rclcpp::spin_until_future_complete(client_node_, future) == rclcpp::FutureReturnCode::SUCCESS) {
return future.get()->result;
} else {
throw std::runtime_error("Service call failed");
}
}
std::shared_ptr<rclcpp::executors::SingleThreadedExecutor> executor_;
std::shared_ptr<GradeCalculator> grade_calculator_node_;
std::thread spin_thread_;
rclcpp::Node::SharedPtr client_node_;
rclcpp::Client<g2_2025_interfaces::srv::Exams>::SharedPtr client_;
};
// ---- TEST CASES ----
TEST_F(GradeCalculatorTest, NormalAverage)
{
EXPECT_EQ(call_service("Alice", {80, 90, 70}), 80);
}
TEST_F(GradeCalculatorTest, WesselBonus)
{
EXPECT_EQ(call_service("Wessel", {80, 90, 70}), 90);
}
TEST_F(GradeCalculatorTest, wesselBonus)
{
EXPECT_EQ(call_service("wessel", {80, 90, 70}), 90);
}
TEST_F(GradeCalculatorTest, GradeTooHigh)
{
EXPECT_EQ(call_service("Wessel", {100, 100, 100}), 100);
}
TEST_F(GradeCalculatorTest, GradeTooLow)
{
EXPECT_EQ(call_service("Alice", {0, 0, 0}), 10);
}