전체 글 269

[단위 테스트] 목과 테스트 취약성

Mock 목과 테스트 취약성 목과 스텁의 구분 - 테스트 대역 유형 테스트 대역 : 더미, 스텁, 스파이, 목, 페이크 목 : 외부로 나가는 상호작용을 모방하고 검사하는 것에 도움. SUT가 상태를 변경하기 위해 의존성을 호출. 스텁 : 내부로 들어오는 상호작용을 모방하는데 도움. SUT가 입력 데이터를 얻기 위한 의존성을 호출. ex) 이메일 발송 -> SMTP 서버 (목 : STMP 서버 상태를 변경) 데이터 검색 SUT가 갖는 의존성을 준비시키는 것이지, 의존성을 준비하는 것을 검증해야할 만큼 의미가 있는 행위가 아니다. -> 과잉 명세, 거짓 양성으로 이어지며 리팩토링 내성을 약화 시킨다. CQS Command Query Separation (명령 조회 분리) 모든 메서드는 명령이거나 조회이어야만..

[단위 테스트] 좋은 단위 테스트의 4대 요소

좋은 단위 테스트를 작성하기 위한 4대 요소 -> 회귀 방지 -> 리팩토링 내성 -> 빠른 피드백 -> 유지 보수성 회귀 방지 간단히 말해서 버그를 방지하는 테스트 코드를 작성하는 것이다. 회귀 방지는 코드의 복잡도, 전체 실행되는 코드 양, 도메인의 중요성에 따라 긴밀하게 작성되어야 한다. 리팩토링 내성 테스트 코드가 테스트하는 실제 로직을 리팩토링 했을 때, 테스트 결과가 빨간불이 나오면 안된다. 이는 테스트 코드의 품질과 높은 연관이 있다. - 거짓 양성 False Positive 거짓 양성으로 판별되는 테스트 코드는 실제 코드가 기능적으로 정상이지만 테스트 결과는 실패를 반환하는 것을 의미한다. "높은 회귀 방지율" 좋은 단위 테스트는 기능 고장이 실제 배포 전에 테스트를 통해 실패가 되어 미리 ..

[단위 테스트] 단위 테스트 구조

좋은 단위 테스트 작성하기 1. AAA 패턴 사용하기 - Given/When/Then으로 지칭하기도 한다. 2. 테스트 코드에서 if 문은 사용하지 말라 - 테스트에서 케이스가 생기는 if문 자체가 안티 패턴이다. 3. 준비 (Arrange) 구절 - 3가지 구절에서 보통 가장 길다. 적절한 디자인 패턴으로 리팩토링을 하여 코드 줄 수를 줄인다. 4. 실행 (Act) 구절 - 실행 구절이 한 줄 인 경우를 피하라. 두 줄 이상의 코드를 호출해야한다면 API 설계가 잘 못 된 것이다. 5. 검증 (Assert) 구절 - 적절한 객체 동등비교 equaltiy 논리를 구현하고 검증 구절을 간소화 한다. 6. 검증 대상 객체 (SUT) - SUT를 지칭하는 변수를 sut라고 작성하는 등 SUT를 구별한다. 테스..

[단위 테스트] 단위 테스트 정의와 활용

'단위 테스트' 정의 -> 작은 코드 조각을 검증하고 -> 빠르게 수행하고 -> 격리된 방식을 처리하는 자동화된 테스트 고전파 vs 런던파 런던파에서는 테스트 대상 시스템(SUT)를 협력자에게서 격리하는 것을 의미. 모든 협력자는 테스트 대역으로 대체. 쉽게 말해서 테스트 대상 객체가 아닌 다른 객체에 의해 테스트가 실패할 요인을 없애는 것. ex) 타이어(Tire) 객체에 의존하는 자동차(Car) 객체 class Tire { public: virtual void run() { } }; class Car { private: Tire tire; public: Car(Tire _tire) : tire(_tire) { } void run() { tire.run(); } }; 런던파에서는 Tire를 테스트 대역..

[단위 테스트] 단위 테스트란

단위 테스트의 목적 지속 가능한 소프트웨어 개발을 위한 방법. 테스트가 없는 소프트웨어 개발을 하다보면 오류에 취약하고 확장성이 없는 코드를 만들어 내기 시작하고 이것이 어느 순간 부터 버그를 눈덩이처럼 만들기 시작하면 버그를 수정하기 위한 시간을 더 많이 소비해 결국 실질 작업 속도를 잡아먹는 다는 이야기 좋은 테스트란? -> 기반 코드를 리팩토링하면서 테스트 코드도 신경쓰며 리팩토링하는 것 -> 각 코드 변경시 테스트를 실행 -> 테스트가 잘못된 경고를 발생시킬 경우 해결 -> 기본 코드가 어떻게 동작하고 이해하려고 할 때는 테스트를 읽는 데 투자 코드 커버리지 - 테스트가 커버하는 비지니스 로직의 비율은 얼마나 되는 가? - 비지니스 로직의 일부분중 테스트가 커버하는 부분이 없지는 않는 가? 테스트..

[Functional C++] 함수형 프로그래밍 (3) 파셜 어플리케이션과 커링

파셜 어플리케이션과 커링에 대해 알아본다. C++ 17 기준을 요한다. 파셜 어플리케이션 N개의 인자를 가진 함수에서 하나의 인자를 바인딩(결정)하여 N-1개의 인자를 가진 함수를 만들어내는 것. 두 개의 인자를 가지는 add 함수에 첫번째 함수 인자를 결정하여 increment 함수를 만든다. auto add = [](const int first, const int second) { return first + second; }; //auto increment = partialApplication(add, 1); // 위 코드는 다음과 동치이다. auto increment = [](const int second) { return 1 + second; }; C++ 파셜 어플리케이션 기존 함수를 재사용하는 ..

Advanced C++ 2022.10.08

[Functional C++] 함수형 프로그래밍 (2) 합성 함수

람다로 표현할 수 있는 합성 함수를 알아본다. doctest 예시로 들 여러 함수에 대해 유닛 테스트를 수행할 수 있는 헤더만 존재하는 오픈 소스를 사용한다. https://github.com/doctest/doctest GitHub - doctest/doctest: The fastest feature-rich C++11/14/17/20 single-header testing framework The fastest feature-rich C++11/14/17/20 single-header testing framework - GitHub - doctest/doctest: The fastest feature-rich C++11/14/17/20 single-header testing framework gith..

Advanced C++ 2022.10.04

[Functional C++] 함수형 프로그래밍 (1) 불변성과 순수 함수

C++으로 함수형 프로그래밍을 작성하는 방법을 알아본다. 함수형 프로그래밍이 필요한 이유 짝수의 합, 홀수의 합, 모든 합을 구하는 예시 프로그램 struct Sums { int evenSum; int oddSum; int totalSum; }; const Sums sums(const vector& numbers) { Sums theTotals; for (auto iter = numbers.begin(); iter != numbers.end(); ++iter){ int number = *iter; if (number % 2 == 0) theTotals.evenSum += number; if (number % 2 == 1) theTotals.oddSum += number; theTotals.totalSum..

Advanced C++ 2022.10.03

정적 라이브러리, 동적 라이브러리

라이브러리 관련 지식 정리. Library 라이브러리란 사용하고자하는 함수를 미리 컴파일하여 목적 코드로 만든 이후 목적 코드를 모아 만든 .lib을 링크하여 사용하는 것을 라이브러리라고 한다. 정적 라이브러리 Static Library (.lib 혹은 .a) 정적 라이브러리를 사용하여 자신의 프로젝트 코드를 컴파일 할 때 컴파일러는 사용자 함수에서 라이브러리 함수를 호출하는 경우 해당 함수의 목적 코드를 크게 두 가지 형태로 실행 파일에 담는다. 1. 사용자 함수를 목적 코드로 만드는 과정에서 라이브러리 함수 내용도 같이 담을 수 있다. (주로 인라인이 가능한 함수들) 2. 라이브러리 함수나 프로시저의 내용이 클 경우 등 해당 라이브러리 함수나 프로시저 실행 명령어(목적 코드)를 실행 파일에 포함시키되..

[C++] Protobuf (Google Protocol Buffer) 라이브러리

Protobuf JSON과 같은 메시지 직렬화/역직렬화 라이브러리로 이진 데이터 직렬화로 효율적인 메모리 사용하고 빠른 메시지 파싱 및 다중 언어를 지원한다는 특징이 있다. 메시지의 프로토콜은 .proto 파일로 정의하여 protoc라는 실행 파일로 (cpp의 경우) .pb.h / pb.cc를 자동 생성한다. message Person { optional string name = 1; optional int32 id = 2; optional string email = 3; } Protobuf의 직렬화 원리 다음 글을 읽어보면 좋다. 기본적으로 Key-Value 쌍으로 이루어진 이진 데이터로 인코딩 되는데 https://medium.com/naver-cloud-platform/nbp-%EA%B8%B0%EC..

Advanced C++ 2022.09.27