Nice programing

단위 테스트 C 코드

nicepro 2020. 9. 28. 10:06
반응형

단위 테스트 C 코드


나는 올 여름 C로 작성된 임베디드 시스템에서 일했다. 내가 일하던 회사가 인수 한 기존 프로젝트였다. JUnit을 사용하여 Java로 단위 테스트를 작성하는 데 익숙해졌지만 기존 코드 (리팩토링이 필요함)와 시스템에 추가 된 새 코드에 대한 단위 테스트를 작성하는 가장 좋은 방법이별로 없었습니다.

JUnit을 사용하여 Java 코드를 단위 테스트하는 것만 큼 쉽게 일반 C 코드를 단위 테스트 할 수있는 프로젝트가 있습니까? 임베디드 개발 (arm-linux 플랫폼에 대한 크로스 컴파일)에 특별히 적용 할 수있는 모든 통찰력은 대단히 감사하겠습니다.


C의 단위 테스트 프레임 워크 중 하나는 Check입니다 . C의 단위 테스트 프레임 워크 목록은 여기 에서 찾을 수 있으며 아래에 재현되어 있습니다. 런타임에있는 표준 라이브러리 함수의 수에 따라 그 중 하나를 사용하거나 사용하지 못할 수 있습니다.

AceUnit

AceUnit (Advanced C 및 Embedded Unit)은 자체적으로 편안한 C 코드 단위 테스트 프레임 워크라고합니다. JUnit 4.x를 모방하고 반사와 유사한 기능을 포함합니다. AceUnit은 임베디드 소프트웨어 개발과 같은 리소스 제약 환경에서 사용할 수 있으며, 중요한 것은 단일 표준 헤더 파일을 포함 할 수없고 ANSI / ISO C 라이브러리에서 단일 표준 C 함수를 호출 할 수없는 환경에서도 잘 실행됩니다. 또한 Windows 포트가 있습니다. 저자는 이러한 기능을 추가하는 데 관심을 표명했지만 신호를 트랩하는 데 포크를 사용하지 않습니다. AceUnit 홈페이지를 참조하십시오 .

GNU Autounit

별도의 주소 공간에서 단위 테스트를 실행하는 것을 포함하여 Check와 같은 행을 많이 따릅니다 (사실 Check의 원래 작성자는 GNU Autounit에서 아이디어를 차용했습니다). GNU Autounit은 GLib를 광범위하게 사용합니다. 즉, 링크 및 이러한 작업에는 특별한 옵션이 필요하지만 이는 특히 GTK 또는 GLib를 이미 사용하고있는 경우 큰 문제가 아닐 수 있습니다. GNU Autounit 홈페이지를 참조하십시오 .

cUnit

또한 GLib를 사용하지만 단위 테스트의 주소 공간을 보호하기 위해 분기하지 않습니다.

CUnit

Win32 GUI 구현 계획이있는 표준 C. 현재는 단위 테스트의 주소 공간을 분기하거나 보호하지 않습니다. 초기 개발. CUnit 홈페이지를 참조하십시오 .

CuTest

소스 트리에 드롭하는 .c 및 .h 파일 하나만있는 간단한 프레임 워크. CuTest 홈페이지를 참조하십시오 .

CppUnit

C ++를위한 최고의 단위 테스트 프레임 워크; C 코드를 테스트하는 데 사용할 수도 있습니다. 안정적이고 활발하게 개발되었으며 GUI 인터페이스가 있습니다. C 용 CppUnit을 사용하지 않는 주된 이유는 첫 번째는 상당히 크고 두 번째는 C ++로 테스트를 작성해야한다는 것입니다. 즉, C ++ 컴파일러가 필요합니다. 이것이 문제처럼 들리지 않는다면 다른 C ++ 단위 테스트 프레임 워크와 함께 고려해 볼 가치가 있습니다. CppUnit 홈페이지를 참조하십시오 .

embUnit

embUnit (Embedded Unit)은 임베디드 시스템을위한 또 다른 단위 테스트 프레임 워크입니다. 이것은 AceUnit으로 대체 된 것으로 보입니다. 임베디드 유닛 홈페이지 .

MinUnit

최소한의 매크로 세트가 전부입니다! 요점은 코드 단위 테스트가 얼마나 쉬운 지 보여주는 것입니다. MinUnit 홈페이지를 참조하십시오 .

안도 씨의 CUnit

상당히 새롭고 아직 초기 개발 단계에있는 CUnit 구현입니다. Mr. Ando 홈페이지를 참조하십시오 .

이 목록은 2008 년 3 월에 마지막으로 업데이트되었습니다.

더 많은 프레임 워크 :

CMocka

CMocka는 모의 객체를 지원하는 C 용 테스트 프레임 워크입니다. 사용 및 설정이 쉽습니다.

CMocka 홈페이지를 참조하십시오 .

표준

Criterion은 자동 테스트 등록, 매개 변수화 된 테스트, 이론을 지원하며 TAP 및 JUnit XML을 포함한 여러 형식으로 출력 할 수있는 크로스 플랫폼 C 단위 테스트 프레임 워크입니다. 각 테스트는 자체 프로세스에서 실행되므로 필요한 경우 신호 및 충돌을보고하거나 테스트 할 수 있습니다.

자세한 내용은 Criterion 홈페이지 를 참조하십시오.

HWUT

HWUT는 C를 완벽하게 지원하는 일반 단위 테스트 도구입니다. Makefile을 만들고, 최소 '반복 테이블'로 코딩 된 대규모 테스트 케이스를 생성하고, 상태 머신을 살펴보고, C- 스텁을 생성하는 등의 작업을 수행 할 수 있습니다. 일반적인 접근 방식은 매우 독특합니다. 평결은 '좋은 표준 출력 / 나쁜 표준 출력'을 기반으로합니다. 그러나 비교 기능은 유연합니다. 따라서 모든 유형의 스크립트를 검사에 사용할 수 있습니다. 표준 출력을 생성 할 수있는 모든 언어에 적용될 수 있습니다.

HWUT 홈페이지를 참조하십시오 .

C 그린

C 및 C ++ 용 현대적이고 이식 가능한 언어 간 단위 테스트 및 모의 프레임 워크입니다. 선택적 BDD 표기법, 모의 라이브러리, 단일 프로세스에서 실행할 수있는 기능 (디버깅을 더 쉽게하기 위해)을 제공합니다. 테스트 기능을 자동으로 검색하는 테스트 실행기를 사용할 수 있습니다. 그러나 프로그래밍 방식으로 직접 만들 수 있습니다.

이러한 모든 기능 (및 그 이상)은 CGreen 설명서에 설명되어 있습니다 .

Wikipedia는 List of unit testing frameworks : C 아래에 C 단위 테스트 프레임 워크의 자세한 목록을 제공합니다 .


개인적으로 저는 Google Test 프레임 워크를 좋아합니다 .

C 코드를 테스트하는 데있어 정말 어려운 점은 외부 모듈에 대한 종속성을 깨뜨려 코드를 단위로 분리 할 수 ​​있다는 것입니다. 레거시 코드를 테스트하려고 할 때 특히 문제가 될 수 있습니다. 이 경우 종종 링커를 사용하여 테스트에서 스텁 함수를 사용합니다.

이것은 사람들이 " 솔기 " 에 대해 말할 때 언급하는 것 입니다. C에서 유일한 옵션은 전 처리기 또는 링커를 사용하여 종속성을 조롱하는 것입니다.

내 C 프로젝트 중 하나의 일반적인 테스트 스위트는 다음과 같습니다.

#include "myimplementationfile.c"
#include <gtest/gtest.h>

// Mock out external dependency on mylogger.o
void Logger_log(...){}

TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0));
}

실제로 헤더 파일이 아닌 C 파일을 포함하고 있다는 점에 유의하십시오 . 이는 모든 정적 데이터 멤버에 대한 액세스의 이점을 제공합니다. 여기에서 로거를 조롱합니다 (logger.o에있을 수 있고 빈 구현을 제공합니다. 이는 테스트 파일이 나머지 코드베이스와 독립적으로 컴파일 및 링크되고 격리 된 상태로 실행됨을 의미합니다.

코드를 교차 컴파일하려면이 작업을 수행하려면 타겟에 대한 좋은 기능이 필요합니다. PowerPC 아키텍처에서 Linux로 컴파일 된 googletest로이 작업을 수행했습니다. 결과를 수집하기 위해 전체 쉘과 OS가 있기 때문에 이것은 의미가 있습니다. 덜 풍부한 환경 (전체 OS가없는 것으로 분류)의 경우 호스트에서 빌드하고 실행해야합니다. 어쨌든 빌드의 일부로 테스트를 자동으로 실행할 수 있도록이 작업을 수행해야합니다.

OO 코드가 일반적으로 절차 적 코드보다 훨씬 덜 결합되어 있다는 사실 때문에 C ++ 코드를 테스트하는 것이 일반적으로 훨씬 쉽다는 것을 알았습니다 (물론 이것은 코딩 스타일에 따라 많이 달라집니다). 또한 C ++에서 종속성 주입 및 메서드 재정의와 같은 트릭을 사용하여 다른 방법으로 캡슐화 된 코드로 이음새를 가져올 수 있습니다.

Michael Feathers는 레거시 코드 테스트에 대한 훌륭한 책을 가지고 있습니다 . 한 장에서 그는 내가 강력히 추천하는 OO가 아닌 코드를 다루는 기술을 다룹니다.

편집 : GitHub 에서 소스를 사용할 수있는 단위 테스트 절차 코드에 대한 블로그 게시물을 작성했습니다 .

Edit: There is a new book coming out from the Pragmatic Programmers that specifically addresses unit testing C code which I highly recommend.


Minunit is an incredibly simple unit testing framework. I'm using it to unit test c microcontroller code for avr.


I'm currently using the CuTest unit test framework:

http://cutest.sourceforge.net/

It's ideal for embedded systems as it's very lightweight and simple. I had no problems getting it to work on the target platform as well as on the desktop. In addition to writing the unit tests, all that's required is:

  • a header file included wherever you're calling the CuTest routines
  • a single additional 'C' file to be compiled/linked into the image
  • some simple code added to to main to set up and call the unit tests - I just have this in a special main() function that gets compiled if UNITTEST is defined during the build.

The system needs to support a heap and some stdio functionality (which not all embedded systems have). But the code is simple enough that you could probably work in alternatives to those requirements if your platform doesn't have them.

With some judicious use of extern "C"{} blocks it also supports testing C++ just fine.


I say almost the same as ratkok but if you have a embedded twist to the unit tests then...

Unity - Highly recommended framework for unit testing C code.

The examples in the book that is mentioned in this thread TDD for embedded C are written using Unity (and CppUTest).


You also might want to take a look at libtap, a C testing framework which outputs the Test Anything Protocol (TAP) and thus integrates well with a variety of tools coming out for this technology. It's mostly used in the dynamic language world, but it's easy to use and becoming very popular.

An example:

#include <tap.h>

int main () {
    plan(5);

    ok(3 == 3);
    is("fnord", "eek", "two different strings not that way?");
    ok(3 <= 8732, "%d <= %d", 3, 8732);
    like("fnord", "f(yes|no)r*[a-f]$");
    cmp_ok(3, ">=", 10);

    done_testing();
}

There is an elegant unit testing framework for C with support for mock objects called cmocka. It only requires the standard C library, works on a range of computing platforms (including embedded) and with different compilers.

It also has support for different message output formats like Subunit, Test Anything Protocol and jUnit XML reports.

cmocka has been created to also work on embedded platforms and also has Windows support.

A simple test looks like this:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

The API is fully documented and several examples are part of the source code.

To get started with cmocka you should read the article on LWN.net: Unit testing with mock objects in C

cmocka 1.0 has been released February 2015.


I didn't get far testing a legacy C application before I started looking for a way to mock functions. I needed mocks badly to isolate the C file I want to test from others. I gave cmock a try and I think I will adopt it.

Cmock scans header files and generates mock functions based on prototypes it finds. Mocks will allow you to test a C file in perfect isolation. All you will have to do is to link your test file with mocks instead of your real object files.

Another advantage of cmock is that it will validate parameters passed to mocked functions, and it will let you specify what return value the mocks should provide. This is very useful to test different flows of execution in your functions.

Tests consist of the typical testA(), testB() functions in which you build expectations, call functions to test and check asserts.

The last step is to generate a runner for your tests with unity. Cmock is tied to the unity test framework. Unity is as easy to learn as any other unit test framework.

Well worth a try and quite easy to grasp:

http://sourceforge.net/apps/trac/cmock/wiki

Update 1

Another framework I am investigating is Cmockery.

http://code.google.com/p/cmockery/

It is a pure C framework supporting unit testing and mocking. It has no dependency on ruby (contrary to Cmock) and it has very little dependency on external libs.

It requires a bit more manual work to setup mocks because it does no code generation. That does not represent a lot of work for an existing project since prototypes won't change much: once you have your mocks, you won't need to change them for a while (this is my case). Extra typing provides complete control of mocks. If there is something you don't like, you simply change your mock.

No need of a special test runner. You only need need to create an array of tests and pass it to a run_tests function. A bit more manual work here too but I definitely like the idea of a self-contained autonomous framework.

Plus it contains some nifty C tricks I didn't know.

Overall Cmockery needs a bit more understanding of mocks to get started. Examples should help you overcome this. It looks like it can do the job with simpler mechanics.


As a C newbie, I found the slides called Test driven development in C very helpful. Basically, it uses the standard assert() together with && to deliver a message, without any external dependencies. If someone is used to a full stack testing framework, this probably won't do :)


We wrote CHEAT (hosted on GitHub) for easy usability and portability.

It has no dependencies and requires no installation or configuration. Only a header file and a test case is needed.

#include <cheat.h>

CHEAT_TEST(mathematics_still_work,
    cheat_assert(2 + 2 == 4);
    cheat_assert_not(2 + 2 == 5);
)

Tests compile into an executable that takes care of running the tests and reporting their outcomes.

$ gcc -I . tests.c
$ ./a.out
..
---
2 successful of 2 run
SUCCESS

It has pretty colors too.


There is CUnit

And Embedded Unit is unit testing framework for Embedded C System. Its design was copied from JUnit and CUnit and more, and then adapted somewhat for Embedded C System. Embedded Unit does not require std C libs. All objects are allocated to const area.

And Tessy automates the unit testing of embedded software.


I don't use a framework, I just use autotools "check" target support. Implement a "main" and use assert(s).

My test dir Makefile.am(s) look like:

check_PROGRAMS = test_oe_amqp

test_oe_amqp_SOURCES = test_oe_amqp.c
test_oe_amqp_LDADD = -L$(top_builddir)/components/common -loecommon
test_oe_amqp_CFLAGS = -I$(top_srcdir)/components/common -static

TESTS = test_oe_amqp

Michael Feather's book "Working Effectively with Legacy Code" presents a lot of techniques specific to unit testing during C development.

There are techniques related to dependency injection that are specific to C which I haven't seen anywhere else.


CppUTest - Highly recommended framework for unit testing C code.

The examples in the book that is mentioned in this thread TDD for embedded C are written using CppUTest.


I use CxxTest for an embedded c/c++ environment (primarily C++).

I prefer CxxTest because it has a perl/python script to build the test runner. After a small slope to get it setup (smaller still since you don't have to write the test runner), it's pretty easy to use (includes samples and useful documentation). The most work was setting up the 'hardware' the code accesses so I could unit/module test effectively. After that it's easy to add new unit test cases.

As mentioned previously it is a C/C++ unit test framework. So you will need a C++ compiler.

CxxTest User Guide CxxTest Wiki


other than my obvious bias

http://code.google.com/p/seatest/

is a nice simple way to unit test C code. mimics xUnit


After reading Minunit I thought a better way was base the test in assert macro which I use a lot like defensive program technique. So I used the same idea of Minunit mixed with standard assert. You can see my framework (a good name could be NoMinunit) in k0ga's blog


cmockery at http://code.google.com/p/cmockery/


Google has excellent testing framework. https://github.com/google/googletest/blob/master/googletest/docs/primer.md

And yes, as far as I see it will work with plain C, i.e. doesn't require C++ features (may require C++ compiler, not sure).


Cmockery is a recently launched project that consists on a very simple to use C library for writing unit tests.


First, look here: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C

My company has a C library our customers use. We use CxxTest (a C++ unit test library) to test the code. CppUnit will also work. If you're stuck in C, I'd recommend RCUNIT (but CUnit is good too).


If you are familiar with JUnit then I recommend CppUnit. http://cppunit.sourceforge.net/cppunit-wiki

That is assuming you have c++ compiler to do the unit tests. if not then I have to agree with Adam Rosenfield that check is what you want.


I used RCUNIT to do some unit testing for embedded code on PC before testing on the target. Good hardware interface abstraction is important else endianness and memory mapped registers are going to kill you.


try lcut! - http://code.google.com/p/lcut


API Sanity Checker — test framework for C/C++ libraries:

An automatic generator of basic unit tests for a shared C/C++ library. It is able to generate reasonable (in most, but unfortunately not all, cases) input data for parameters and compose simple ("sanity" or "shallow"-quality) test cases for every function in the API through the analysis of declarations in header files.

The quality of generated tests allows to check absence of critical errors in simple use cases. The tool is able to build and execute generated tests and detect crashes (segfaults), aborts, all kinds of emitted signals, non-zero program return code and program hanging.

Examples:


One technique to use is to develop the unit test code with a C++ xUnit framework (and C++ compiler), while maintaining the source for the target system as C modules.

Make sure you regularly compile your C source under your cross-compiler, automatically with your unit tests if possible.


LibU (http://koanlogic.com/libu) has an unit test module that allows explicit test suite/case dependencies, test isolation, parallel execution and a customizable report formatter (default formats are xml and txt).

The library is BSD licensed and contains many other useful modules - networking, debugging, commonly used data structures, configuration, etc. - should you need them in your projects ...


I'm surprised that no one mentioned Cutter (http://cutter.sourceforge.net/) You can test C and C++, it seamlessly integrates with autotools and has a really nice tutorial available.


In case you are targeting Win32 platforms or NT kernel mode, you should have a look at cfix.


If you're still on the hunt for test frameworks, CUnitWin32 is one for the Win32/NT platform.

This solves one fundamental problem that I faced with other testing frameworks. Namely global/static variables are in a deterministic state because each test is executed as a separate process.

참고URL : https://stackoverflow.com/questions/65820/unit-testing-c-code

반응형