SW 그리고 아빠 엔지니어링 중...

아는 만큼 보이고, 경험해봐야 알 수 있고, 자꾸 써야 내 것이 된다.

개발/환경구축

mock object(모의 객체) 파일 자동 생성 툴

보리남편 김 주부 2023. 9. 12. 09:00
* 본 글은 모의 객체에 대한 설명이 아니기에 mock object에 대한 이해는 약식으로 정리한 others 혹은 참조 링크 내용에서 확인 부탁 드립니다.

 

 

 

Unit Test를 한다면 마주하는 의존성 제거 문제


Unit Test를 진행하다 보면 의존성 제거를 위해 테스트가 원활하지 않은 경우가 있는데 이때 의존성 제거를 위해 gtest mock이 있지만 그냥은 사용할 수 없고 별도의 mock class(혹은 파일)을 우선 생성해야 한다.

Android Studio와 같이 JAVA 기반 IDE를 써보면 새로운 파일 생성 시 자동으로 xxxTest 클래스를 생성하는 데, 이전 글(당신의 회사는 Test 도구가 있는가?)에서도 확인하였지만 VS는 테스트 도구를 Enterprise 버전부터 지원하기에 자체적을 방법을 강구해야 한다.

 

gmock


gtest 공식 사이트에 googlemock도 있었고 자동으로 mock 파일을 생성해 주는 파일도 있었다. 하지만 GoogleTest로 합치면서 사라졌기에 대처할 수 있는 툴이 필요하다.
https://github.com/google/googlemock

Boost Software License, Version 1.0.이다. 👍👍👍

 

1. gmock 파일 다운로드

1) github에서 코드를 다운로드 받는다.

   - 실상 gmock.py 파일과 gmock.conf파일이 있으면 된다.

https://github.com/cpp-testing/gmock.py

 

GitHub - cpp-testing/gmock.py: 'Google Mock' mocks generator based on libclang

'Google Mock' mocks generator based on libclang. Contribute to cpp-testing/gmock.py development by creating an account on GitHub.

github.com

 

2. 환경세팅

0) python과 libclang이 필요하다.

Requirements
  • python (tested with 2.7 and 3.3)
  • libclang (tested with 3.2 and 3.3)

 

1) VS에서 python 설치하기

도구 > 확장 및 업데이트에서 python 설치

만약 python을 설치하고도 실행 시 아래와 같은 에러가 뜬다면

1-1) 설치된 python에 clang module 추가가 필요하다.

VS 설치 위치 아래 python 실행파일이 있는데 그 하위 script에 pip가 있음(pip는 python의 패키지 모듈 인스톨러)

https://pypi.org/project/clang/ 에서 clang 패키지 확인

 

1-2) python에 clang 패키지가 설치되어도 결국 clang을 설치하지 않으면 사용할 수 없다.

 

2) clang을 위해 llvm 설치

VS에서는 2019부터 지원을 하니 2019를 쓰시는 분은 다음으로 패스~
https://learn.microsoft.com/ko-kr/cpp/build/clang-support-msbuild?view=msvc-170
LLVM(low level virtual machine)은 컴파일러 인프라스트럭쳐이다. LLVM을 이용해서 여러 프로젝트를 컴파일할 수 있는데 대표적인 프로젝트가 clang이다.
clang은 c 계열(c, c++, objective C, objective C++) 컴파일을 사용하기 위한 LLVM에 속한 컴파일러이다.

 

3. 사용 방법

아래 옵션 규칙을 사용하여 mock 파일을 생성할 수 있다.

Usage
Usage: gmock.py [options] files...

Options:
  -h, --help                show this help message and exit
  -c FILE, --config=FILE    config FILE (default='gmock.conf')
  -d DIR, --dir=DIR         dir for generated mocks (default='.')
  -l LIMIT, --limit=LIMIT   limit to interfaces within declaration (default='')

 

예를 들어 BFS_Graph.h 파일로 예를 들면 아래와 같이 command를 구성할 수 있다.

class Graph {
public:
    map<int, bool> visited;
    map<int, list<int> > adj;
 
    // Function to add an edge to graph
    void addEdge(int v, int w);
 
    // DFS traversal of the vertices
    // reachable from v
    void DFS(int v);
    virtual void delEdge()=0;
    virtual void moveEdge()=0;
};

> python gmock.py -c "gmock.conf" -d "test/mock" BFS_Graph.h

-c "gmock.conf" : gmock.conf를 config 파일로 쓰겠다고 명시하는 옵션, 파일을 열어보면 실제 mock 파일의 코드가 될 templete이다.

-d "test/mock" : 생성하고자 하는 디렉터리 경로 (현재 폴더 기준 상대 경로)

BFS_Graph.h : mock 파일로 만들 class

 

-d 옵션으로 지정한 폴더(없으면 현재 폴더)에 class 이름과 동일한 mock 파일이 생성된다.

생성된 파일을 보면 old style 형식으로 생성이 된다.
하지만 old macro style도 지원한다고 하니 사용하는 것에는 문제가 없을 것 같다.
https://google.github.io/googletest/gmock_cook_book.html#old-style-mock_methodn-macros

 

생성된 mock 파일을 열어보면  순수 가상함수로 정의된 함수만 추출하여 생성됨을 확인할 수 있다.

 

4. 빌드 통합 시 적용방법

빌드 시 본 내용을 적용하면 다른 IDE처럼 mock 파일을 자동으로 생성하는 환경을 갖출 수 있다.

https://github.com/cpp-testing/gmock.py#integration-with-the-build-system

 

GitHub - cpp-testing/gmock.py: 'Google Mock' mocks generator based on libclang

'Google Mock' mocks generator based on libclang. Contribute to cpp-testing/gmock.py development by creating an account on GitHub.

github.com

 

Others


1. 모의 객체를 쓰는 이유?

단위 테스트를 수행할 때, 테스트해야 할 항목이 의존하는 구성요소로부터 격리해서 테스트하고자 할 때 유용하게 사용할 수 있다.

https://kr.mathworks.com/help/matlab/matlab_prog/create-mock-object.html

  • 서비스를 중단시키고, 유닛테스트를 해야 하는 경우
  • 오픈시간 등 제약사항이 있는 외부 API를 사용해야 하는 경우
  • DB 접근 테스트를 해야 하는 경우
  • 미완성된 모듈을 포함해서 테스트해야 하는 경우
  • 유닛테스트가 너무 무거운 경우

 

2. 여러 종류의 모의 객체

목적에 맞게 객체를 생성 및 활용을 해야 한다.

https://codinghack.tistory.com/92

mock에 대해 개론적 이해를 하고 싶다면 아래 사이트 참조
https://codinghack.tistory.com/92
https://eminentstar.github.io/2017/07/24/about-mock-test.html

 

3. gmock 사용 가이드 문서

적용 예시) https://ungodly-hour.tistory.com/17

 

생각해 보기
mock의 용도를 생각해 보면 의존성이 있는 클래스를 분리시켜서 테스트하기 쉬운 코드가 되지만
새로운 파일 생성에 맞춰 mock 클래스가 자동 생성된다 한들 mock을 어떤 용도로 사용할지 판단하는 것 자체가 고민이 되기에 사용하기가 쉽지가 않고, 이것은 TDD 방법론이 널리 사용되지 못하는 이유와 같다
    * TC 창작의 고통, 일정 지연 압박 => 테스트를 포기한 개발/배포 ('필요성 < 비용'이 더 크다.)
그리고 mock을 사용하고 있더라도 유지보수를 하지 않으면 깨지는 유닛테스트가 될 확률이 높다.
 - 실제 사용하는 파일 근처에 mock 파일을 생성하면 관리하기는 편하지만 어느 unit test에 활용되고 있는지 알 수 없으며 깨지는 테스트 케이스 발생 시 인지하게 된다.
- 유닛 테스트 케이스에 mock class를 생성하여 만들어두면 실제 class가 변경이 될 때 함께 유지보수가 되지 못해 잘못된 TC가 방치될 수 있다.
728x90