코드리뷰리팩토링테스트데이터·SQLby affaan-m
C++ TDD 커맨드
C++에 대한 TDD 워크플로우를 적용합니다. GoogleTest 테스트를 먼저 작성한 다음 구현하고 gcov/lcov로 커버리지를 확인합니다.
한 줄 평가 — 다음 사람 도와주세요
언제 쓰나
C++ 코드의 테스트 주도 개발을 할 때 사용합니다.
SKILL.md
Lattice 한국어 번역 · 원본 affaan-m/everything-claude-code (841beea). 복사 → 저장하면 Claude Code가 인식합니다.
---
description: C++에 대한 TDD 워크플로우를 적용합니다. GoogleTest 테스트를 먼저 작성한 다음 구현합니다. gcov/lcov를 사용하여 커버리지를 확인합니다.
---
# C++ TDD 명령
이 명령은 CMake/CTest와 함께 GoogleTest/GoogleMock을 사용하여 C++ 코드에 대한 테스트 주도 개발 방법론을 적용합니다.
## 이 명령이 하는 일
1. **인터페이스 정의**: 클래스/함수 시그니처를 먼저 작성합니다
2. **테스트 작성**: 포괄적인 GoogleTest 테스트 케이스를 작성합니다 (RED)
3. **테스트 실행**: 테스트가 올바른 이유로 실패하는지 확인합니다
4. **코드 구현**: 최소한의 코드를 작성하여 테스트를 통과합니다 (GREEN)
5. **리팩터링**: 테스트를 유지하면서 코드를 개선합니다
6. **커버리지 확인**: 80% 이상의 커버리지를 확인합니다
## 언제 사용할 것인가
다음 경우에 `/cpp-test`를 사용합니다:
- 새로운 C++ 함수 또는 클래스를 구현할 때
- 기존 코드에 테스트 커버리지를 추가할 때
- 버그를 수정할 때 (테스트를 먼저 작성합니다)
- 비즈니스 로직을 구축할 때
- C++의 TDD 워크플로우를 학습할 때
## TDD 사이클
```
RED → 실패하는 GoogleTest 테스트를 작성합니다
GREEN → 최소한의 코드를 작성하여 테스트를 통과합니다
REFACTOR → 코드를 개선하면서 테스트를 유지합니다
REPEAT → 다음 테스트 케이스로 진행합니다
```
## 예제 세션
````
사용자: /cpp-test 이메일 주소를 확인하는 함수가 필요합니다
에이전트:
# TDD 세션: 이메일 확인기
## Step 1: 인터페이스 정의
```cpp
// validator/email.hpp
#pragma once
#include <string>
#include <expected>
enum class EmailError {
빈 문자열,
잘못된 형식
};
std::expected<void, EmailError> validate_email(const std::string& email);
```
## Step 2: 테스트 작성 (RED)
```cpp
// validator/email_test.cpp
#include <gtest/gtest.h>
#include "email.hpp"
TEST(ValidateEmail, 단순한 이메일을 허용합니다) {
auto result = validate_email("user@example.com");
EXPECT_TRUE(result.has_value());
}
TEST(ValidateEmail, 서브도메인을 허용합니다) {
EXPECT_TRUE(validate_email("user@mail.example.com").has_value());
}
TEST(ValidateEmail, 플러스를 허용합니다) {
EXPECT_TRUE(validate_email("user+tag@example.com").has_value());
}
TEST(ValidateEmail, 빈 문자열을 거부합니다) {
auto result = validate_email("");
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error(), EmailError::빈 문자열);
}
TEST(ValidateEmail, @ 기호가 없는 것을 거부합니다) {
EXPECT_FALSE(validate_email("userexample.com").has_value());
}
TEST(ValidateEmail, 도메인이 없는 것을 거부합니다) {
EXPECT_FALSE(validate_email("user@").has_value());
}
TEST(ValidateEmail, 로컬 파트가 없는 것을 거부합니다) {
EXPECT_FALSE(validate_email("@example.com").has_value());
}
```
## Step 3: 테스트 실행 - 실패 확인
```bash
$ cmake --build build && ctest --test-dir build --output-on-failure
1/1 Test #1: email_validator_test .....***Failed
--- undefined reference to `validate_email'
FAIL
```
✓ 테스트가 예상대로 실패합니다 (구현되지 않음).
## Step 4: 최소한의 코드 구현 (GREEN)
```cpp
// validator/email.cpp
#include "email.hpp"
#include <regex>
std::expected<void, EmailError> validate_email(const std::string& email) {
if (email.empty()) {
return std::unexpected(EmailError::빈 문자열);
}
static const std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
if (!std::regex_match(email, pattern)) {
return std::unexpected(EmailError::잘못된 형식);
}
return {};
}
```
## Step 5: 테스트 실행 - 통과 확인
```bash
$ cmake --build build && ctest --test-dir build --output-on-failure
1/1 Test #1: email_validator_test ..... Passed 0.01 sec
100% tests passed.
```
✓ 모든 테스트가 통과합니다!
## Step 6: 커버리지 확인
```bash
$ cmake -DCMAKE_CXX_FLAGS="--coverage" -B build && cmake --build build
$ ctest --test-dir build
$ lcov --capture --directory build --output-file coverage.info
$ lcov --list coverage.info
validator/email.cpp | 100%
```
✓ 커버리지: 100%
## TDD 완료!
````
## 테스트 패턴
### 기본 테스트
```cpp
TEST(스위트 이름, 테스트 이름) {
EXPECT_EQ(add(2, 3), 5);
EXPECT_NE(result, nullptr);
EXPECT_TRUE(is_valid);
EXPECT_THROW(func(), std::invalid_argument);
}
```
### 픽스처
```cpp
class DatabaseTest : public ::testing::Test {
protected:
void SetUp() override { db_ = create_test_db(); }
void TearDown() override { db_.reset(); }
std::unique_ptr<Database> db_;
};
TEST_F(DatabaseTest, 레코드 삽입) {
db_->insert("키", "값");
EXPECT_EQ(db_->get("키"), "값");
}
```
### 매개변수화된 테스트
```cpp
class PrimeTest : public ::testing::TestWithParam<std::pair<int, bool>> {};
TEST_P(PrimeTest, 소수 확인) {
auto [입력, 예상] = GetParam();
EXPECT_EQ(is_prime(입력), 예상);
}
INSTANTIATE_TEST_SUITE_P(소수, PrimeTest, ::testing::Values(
std::make_pair(2, true),
std::make_pair(4, false),
std::make_pair(7, true)
));
```
## 커버리지 명령
```bash
# 커버리지와 함께 빌드
cmake -DCMAKE_CXX_FLAGS="--coverage" -DCMAKE_EXE_LINKER_FLAGS="--coverage" -B build
# 테스트 실행
cmake --build build && ctest --test-dir build
# 커버리지 보고서 생성
lcov --capture --directory build --output-file coverage.info
lcov --remove coverage.info '/usr/*' --output-file coverage.info
genhtml coverage.info --output-directory coverage_html
```
## 커버리지 대상
| 코드 유형 | 대상 |
|-----------|--------|
| 비즈니스 로직 | 100% |
| 공용 API | 90%+ |
| 일반 코드 | 80%+ |
| 생성된 코드 | 제외 |
## TDD 모범 사례
**DO:**
- 테스트를 먼저 작성하고, 구현을 나중에 합니다
- 각 변경 후 테스트를 실행합니다
- `EXPECT_*` (계속) 대신 `ASSERT_*` (중지)를 사용합니다
- 동작을 테스트하고, 구현 세부 사항은 테스트하지 않습니다
- 에지 케이스 (빈 문자열, null, 최대 값, 경계 조건)를 포함합니다
**DON'T:**
- 구현을 먼저 작성하고, 테스트를 나중에 합니다
- RED 단계를 건너뜁니다
- 사적 메서드를 직접 테스트합니다 (공용 API를 통해 테스트합니다)
- 테스트에서 `sleep`을 사용합니다
- 불안정한 테스트를 무시합니다
## 관련 명령
- `/cpp-build` - 빌드 오류 수정
- `/cpp-review` - 구현 후 코드 검토
- `verification-loop` 스킬 - 전체 검증 루프 실행
## 관련
- 스킬: `skills/cpp-testing/`
- 스킬: `skills/tdd-workflow/`필요한 도구
호버하면 설명CC
설치 + 호출 (2단계)
Claude Code CLI 기준.
- 1
SKILL.md 저장
아래 버튼으로 복사 → 다음 경로로 저장.
~/.claude/skills/everything-claude-code-c-tdd/SKILL.md - 2
호출
Claude Code 채팅창에서 자연어로 부르면 자동 발동:
예) C++ 코드의 테스트 주도 개발을 할 때 사용합니다
트리거가 안 잡히면 SKILL.md의
description줄에 더 구체적인 한국어 키워드를 추가해보세요.