programing

정적 함수 테스트 방법

yoursource 2022. 12. 31. 18:45
반응형

정적 함수 테스트 방법

일부 C코드에 unit-test를 적용하면서 소스 코드를 수정하지 않으면 테스트 파일에서 일부 정적 함수를 호출할 수 없다는 문제가 발생했습니다.이 문제를 해결할 수 있는 간단하고 합리적인 방법이 있을까요?

테스트용 하네스를 가지고 있습니다.정적 함수를 테스트하는 것과 같은 심각한 경우에는 다음을 사용합니다.

#include "code_under_test.c"
...test framework...

즉, 테스트 대상 기능을 포함하는 파일 전체를 테스트 하니스에 포함합니다.그것은 최후의 수단이지만 효과가 있다.

함수를 호출할 수 없는 이유에 대해 좀 더 자세히 설명해 주시겠습니까?

.c 파일에는 비공개이기 때문에 사용할 수 없습니까?그렇다면 다른 컴파일 유닛이 함수에 액세스할 수 있도록 함수에 액세스할 수 있는 조건부 컴파일을 사용하는 것이 가장 좋습니다.예를들면

Some Header Somewher.h

#if UNIT_TEST
#define unit_static 
#else
#define unit_static static
#endif

푸우

#if UNIT_TEST
void some_method
#endif

Foo.cpp

unit_static void some_method() ...
#define static

이것은 매우 나쁜 생각이다.함수에 대해 로컬로 선언된 변수가 있는 경우 함수의 동작이 변경됩니다.예:

static int func(int data)
{
   static int count = 0;

   count += data;
   return count;
}

유닛 테스트에서 함수를 호출할 수 있습니다.func()는 내보내지만 코드의 기본 기능은 변경됩니다.

--마이너스

유닛 테스트에서는 실제로 소스 파일 자체에 테스트 코드가 있으며 테스트 시 조건부로 컴파일합니다.이를 통해 장치 테스트는 모든 함수 및 파일 수준 변수(정적 변수 또는 기타)에 대한 전체 액세스를 제공합니다.

유닛 테스트 자체는 정적인 것이 아닙니다.이것에 의해, 유닛이 모든 컴파일 유닛을 테스트하는 단일의 슈퍼 테스트 프로그램에서 유닛 테스트를 호출할 수 있습니다.

코드를 출하할 때는 유닛 테스트를 조건부로 컴파일하지만 실제로는 필요하지 않습니다(테스트한 코드와 동일한 코드를 출하하고 있는지 확인하고 싶다면).

테스트하는 코드와 같은 장소에서 유닛 테스트를 실시하는 것은 매우 중요합니다.코드 변경 시 테스트 갱신이 필요하기 때문입니다.

정적 기능은 기본적으로 공공(즉, 노출된) 기능에 대한 도우미 기능입니다.따라서 IMO, 유닛테스트에서는 스태틱함수의 모든 패스를 실행하는 입력을 사용하여 퍼블릭인터페이스를 호출해야 합니다.

공공 기능의 출력(반환값/부작용)을 사용하여 정전기 효과를 테스트해야 한다.

이것은 이러한 부작용을 '잡기' 위해 적절한 스텁을 가질 필요가 있다는 것을 의미한다.(예를 들어 함수가 파일 IO를 호출하는 경우 이러한 파일 IO lib 함수를 재정의하려면 stub를 제공해야 합니다).이를 위해서는 각 테스트 스위트를 별도의 프로젝트/실행 파일로 만들고 외부 lib 함수에 링크하지 않도록 하는 것이 가장 좋습니다.C기능도 조롱할 수 있지만 그럴 가치가 없습니다.

어쨌든, 이것은 지금까지의 어프로치이며, 나에게도 효과가 있습니다.행운을 빌어요

Jonathan Leffler에 의해 받아들여진 답변에 덧붙여 포장지 기능에 대한 다른 사람의 언급에 대해 자세히 설명하겠습니다.

  1. test_wrapper_foo.c와 같이 테스트소스 파일을 만듭니다.여기서 foo.c는 원래 파일입니다.
  2. test_wrapper_foo.c의 경우:
#include "foo.c"   

// Prototype
int test_wrapper_foo();

// wrapper function
int test_wrapper_foo() {
    // static function to test
    return foo();
}

foo.c의 정적 함수 foo가 다음과 같은 프로토타입을 갖는다고 가정한다: int foo(void).

  1. foo.c 대신 makefile을 사용하여 test_build test_foo.c를 만듭니다(다른 외부 함수에 의한 foo.c의 함수에 대한 의존성은 해소되지 않습니다).

  2. 유닛 테스트스크립트에서는 foo() 대신 test_wrapper_foo()를 호출합니다.

이 방법을 사용하면 원래 소스가 그대로 유지되고 테스트 프레임워크에서 함수에 액세스할 수 있습니다.

추가 헤더를 할 수 .yourheader_static.h및 파일 변환 obj 파일 변환code_under_test.o through를 통해.objdump --globalize-symbols=syms_name_file이치노비정적 기능인 것처럼 표시됩니다.

아니요 - 소스를 약간 수정하지 않으면 정적 함수를 직접 테스트할 수 없습니다(다른 파일의 함수에서 호출할 수 없다는 C의 정적 정의).

테스트 파일 내에 정적 함수만 호출하는 별도의 함수를 만들 수 있습니까?

예를 들어 다음과 같습니다.

//Your fn to test
static int foo(int bar)
{
  int retVal;
  //do something
  return retVal;
}

//Wrapper fn
int test_foo(int bar)
{
  return foo(bar);
}

통상, 스태틱 기능을 직접 테스트하는 것은 아니고, 콜 함수의 다른 테스트에 의해서, 실행하는 로직이 적절히 테스트되고 있는 것을 확인합니다.

위의 모든 제안 답변(몇 가지 제외)은 조건부 컴파일을 제안하며, 이를 소스로 수정해야 합니다.문제가 되지 않기 때문에 (테스트를 위해) 지저분하기만 하면 됩니다.오히려 이런 걸 할 수 있어요.

테스트할 기능은 다음과 같습니다.

static int foo(int);

testing_headers.h라고 하는 다른 헤더 파일을 만듭니다.이 파일에는 다음 내용이 포함됩니다.

static int foo(int);
int foo_wrapper(int a) {
    return foo(a);
}

테스트용으로 c파일을 컴파일 할 때 컴파일러 옵션에서 이 헤더를 강제로 포함할 수 있습니다.

clang 및 gcc의 경우 플래그는--includeMicrosoft C 컴파일러의 경우,/FI.

이를 위해서는 c파일을 0으로 변경할 필요가 있으며, 함수에 비정적 래퍼를 쓸 수 있습니다.

비 스태틱 래퍼를 원하지 않는 경우 foo로 초기화된 비 스태틱 글로벌 함수 포인터를 만들 수도 있습니다.

그런 다음 이 전역 함수 포인터를 사용하여 함수를 호출할 수 있습니다.

Ceedling을 사용하여 #include "code_under_test.c" 메서드를 사용하려고 하면 #include "code_under_test.c"가 자동으로 빌드되기 때문에 테스트 빌드는 실패합니다.

code_under_test.c 코드를 약간 수정하고 다른 몇 가지 변경을 가함으로써 문제를 해결할 수 있었습니다.code_under_test.c 파일 전체를 다음 체크로 랩합니다.

#if defined(BUILD)
...
#endif // defined(BUILD)

테스트 하니스에 다음을 추가합니다.

#define BUILD
#include "code_under_test.c"

를 추가합니다.BUILDMakefile 또는 프로젝트 구성 파일을 정의합니다.

# Makefile example
..
CFLAGS += -DBUILD
..

이제 사용자 환경과 테스트 하니스에 포함된 파일을 빌드합니다.이제 Ceedling은 두 번째 파일을 빌드할 수 없습니다(project.yml 파일에서 BUILD가 정의되지 않았는지 확인합니다).

두 가지 방법이 있습니다.

  1. c 소스 파일을 유닛테스트 소스 파일에 포함시키면 스태틱 방식이 유닛테스트 소스 파일의 범위에 들어가 콜이 가능하게 됩니다.

  2. 트릭을 하다:

#define static

유닛 테스트 소스 파일의 선두에 있습니다.

키워드를 변환합니다.static'아무것도 없다'고 말할 수 있는 것은, 그것이 제거한다는 것이다.staticc 소스 코드에서 가져옵니다.

일부 유닛 테스트툴에서는 config 옵션 "pre-processor"를 사용하여 이 트릭을 실행할 수 있습니다.config를 입력하기만 하면 됩니다.

static=

툴은 모든 것을 변환합니다.static키워드를 "nothing"으로 설정합니다.

하지만 이런 방법을 사용하면static메서드(또는 변수)는 구체적인 의미를 잃습니다.

스태틱 함수를 추가하여 스태틱함수를 호출한 후 스태틱함수를 호출할 수 있습니다.

static int foo ()
{
   return 3;
}

#ifdef UNIT_TEST
int test_foo ()
{
  if (foo () == 3)
    return 0;

  return 1;
}
#endif

언급URL : https://stackoverflow.com/questions/593414/how-to-test-a-static-function

반응형