-
Notifications
You must be signed in to change notification settings - Fork 37
Open
Labels
good first issueGood for newcomersGood for newcomerstestingTesting related issuesTesting related issues
Description
Description
The Gemini AI provider client (src/providers/gemini/client.cpp) lacks unit tests. Adding tests would improve reliability and catch regressions.
Files
- Existing code:
src/providers/gemini/client.cpp,src/include/gemini_client.h - Test to create:
tests/unit/test_gemini_client.cpp
Task
Create unit tests covering:
-
Request building (
build_request_body):- Generates correct JSON structure with user prompt
- System prompt is included in
systemInstructionfield - Temperature and max_tokens are set in
generationConfig - Handles optional fields correctly
-
Response parsing (
parse_response):- Valid 200 response extracts text from
candidates[0].content.parts[0].text - Non-200 status codes return error response
- Handles missing fields gracefully (missing candidates, content, parts, text)
- Extracts error message from error response JSON
- Valid 200 response extracts text from
-
Error handling:
- Invalid API key error (401)
- Rate limit error (429)
- Malformed response JSON
- Missing required fields in response
Example Test Structure
#include <gtest/gtest.h>
#include <nlohmann/json.hpp>
#include "gemini_client.h"
class GeminiClientTest : public ::testing::Test {
protected:
void SetUp() override {
client_ = std::make_unique<gemini::GeminiClient>("test-api-key");
}
std::unique_ptr<gemini::GeminiClient> client_;
};
TEST_F(GeminiClientTest, BuildRequestBodyIncludesUserPrompt) {
gemini::GeminiRequest request;
request.model = "gemini-2.0-flash";
request.user_prompt = "Generate a query";
request.system_prompt = "";
std::string body = client_->build_request_body(request);
auto json = nlohmann::json::parse(body);
ASSERT_TRUE(json.contains("contents"));
ASSERT_TRUE(json["contents"].is_array());
EXPECT_EQ(json["contents"][0]["parts"][0]["text"], "Generate a query");
}
TEST_F(GeminiClientTest, BuildRequestBodyIncludesSystemPrompt) {
gemini::GeminiRequest request;
request.model = "gemini-2.0-flash";
request.user_prompt = "Generate a query";
request.system_prompt = "You are a SQL expert";
std::string body = client_->build_request_body(request);
auto json = nlohmann::json::parse(body);
ASSERT_TRUE(json.contains("systemInstruction"));
EXPECT_EQ(json["systemInstruction"]["parts"][0]["text"], "You are a SQL expert");
}
TEST_F(GeminiClientTest, BuildRequestBodyIncludesGenerationConfig) {
gemini::GeminiRequest request;
request.model = "gemini-2.0-flash";
request.user_prompt = "Test";
request.temperature = 0.7;
request.max_tokens = 1000;
std::string body = client_->build_request_body(request);
auto json = nlohmann::json::parse(body);
ASSERT_TRUE(json.contains("generationConfig"));
EXPECT_DOUBLE_EQ(json["generationConfig"]["temperature"], 0.7);
EXPECT_EQ(json["generationConfig"]["maxOutputTokens"], 1000);
}
TEST_F(GeminiClientTest, ParseResponseExtractsContent) {
std::string response_body = R"({
"candidates": [{
"content": {
"parts": [{"text": "SELECT * FROM users;"}]
}
}]
})";
auto result = client_->parse_response(response_body, 200);
EXPECT_TRUE(result.success);
EXPECT_EQ(result.text, "SELECT * FROM users;");
}
TEST_F(GeminiClientTest, ParseResponseHandlesHttpError) {
std::string error_body = R"({
"error": {
"code": 401,
"message": "Invalid API key"
}
})";
auto result = client_->parse_response(error_body, 401);
EXPECT_FALSE(result.success);
EXPECT_TRUE(result.error_message.find("Invalid API key") != std::string::npos);
}
TEST_F(GeminiClientTest, ParseResponseHandlesMissingCandidates) {
std::string response_body = R"({"usageMetadata": {}})";
auto result = client_->parse_response(response_body, 200);
EXPECT_FALSE(result.success);
EXPECT_TRUE(result.error_message.find("Invalid response format") != std::string::npos);
}
TEST_F(GeminiClientTest, ParseResponseHandlesMalformedJson) {
std::string response_body = "not valid json {{{";
auto result = client_->parse_response(response_body, 200);
EXPECT_FALSE(result.success);
EXPECT_TRUE(result.error_message.find("parse error") != std::string::npos);
}Acceptance Criteria
- Tests cover
build_request_body()with all optional fields - Tests cover
parse_response()for success and error cases - Tests handle malformed JSON gracefully
- Tests follow existing patterns in
tests/unit/ - All tests pass with
ctest
Skills Required
- C++
- Google Test framework
- JSON handling
Helpful Resources
- Existing tests in
tests/unit/for patterns - Google Test documentation
src/include/gemini_client.hfor the API interface
Difficulty
🟡 Medium
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
good first issueGood for newcomersGood for newcomerstestingTesting related issuesTesting related issues