marunomaruno-memo

marunomaruno-memo

CUnit: C 用 単体テスト・フレームワーク

2012年11月30日 | C / C++
                                                                    2012-11-30
CUnit: C 用 単体テスト・フレームワーク
================================================================================

■ Cunit

Cunit は、 C プログラムの単体テストをするためのフレームワークです。
このドキュメントでは、単純な使い方だけを示します。


ダウンロードとインストール

つぎからダウンロードします
CUnit
http://sourceforge.net/projects/cunit/

任意のフォルダーに展開すればインストール完了です。
このドキュメントでは、
    C:¥CUnit-2.1-0
にインストールしたことにします。


■ サンプル

サンプルとして、指定された西暦年に対して、うるう年か平年かを検査する関数 
isLeapYear() のモジュール LeapYear.c の単体テストを考えます。


□ LeapYear.h
---
/*
 * LeapYear.h
 *
 *  Created on: 2012/08/15
 *      Author: maruno
 */

#ifndef LEAPYEAR_H_
#define LEAPYEAR_H_

/**
 * 西暦 year 年がうるう年かどうか判定する。
 * @param year 西暦年
 * @return うるう年のとき1、平年のとき0
 */
int isLeapYear(int year);


#endif /* LEAPYEAR_H_ */
---


□ LeapYear.c
---
#include "LeapYear.h"

int isLeapYear(int year) {
    if ((year % 4) == 0) {
        if ((year % 100) == 0) {
            return 0;
        }
        if ((year % 400) == 0) {
            return 1;
        }
        return 1;
    }
    return 0;
}
---


■ Cunit の使用法

1. テスト・ドライバーの作成

まず、単体テストを行いたいモジュールのテスト・ドライバーを作ります。

□ LeapYearTest.c
---
#include <stdlib.h>
#include <CUnit.h>
#include <Automated.h>
#include <Basic.h>

#include "LeapYear.h"

void testIsLeapYear001(void);
void testIsLeapYear002(void);
void testIsLeapYear003(void);
void testIsLeapYear004(void);

int main(void) {
    CU_pSuite suite;

    CU_initialize_registry();
    suite = CU_add_suite("isLeapYear", NULL, NULL );
    CU_ADD_TEST(suite, testIsLeapYear001);
    CU_ADD_TEST(suite, testIsLeapYear002);
    CU_ADD_TEST(suite, testIsLeapYear003);
    CU_ADD_TEST(suite, testIsLeapYear004);
    CU_automated_run_tests();            // 結果をXML形式で出力
    CU_basic_set_mode(CU_BRM_NORMAL);    // 結果表示を失敗と実行サマリーにする
    CU_basic_run_tests();    // 結果を標準出力に出力
    CU_cleanup_registry();

    return 0;
}

/**
 * 400の倍数でうるう年
 */
void testIsLeapYear001(void) {
    CU_ASSERT_EQUAL(1, isLeapYear(2000));    // 2つの引数が等しければOK
}

/**
 * 4の倍数でうるう年
 */
void testIsLeapYear002(void) {
    CU_ASSERT_TRUE(isLeapYear(2012));    // 結果がtrueであればOK
}

/**
 * 100の倍数で平年
 */
void testIsLeapYear003(void) {
    CU_ASSERT_FALSE(isLeapYear(2100));    // 結果がfalseであればOK
}

/**
 * 4で割り切れず平年
 */
void testIsLeapYear004(void) {
    CU_ASSERT(0 == isLeapYear(2013));    // 条件式の結果がtrueであればOK
}
---

>gcc -IC:¥CUnit-2.1-0¥include¥CUnit -Wall -c LeapYearTest.c
>gcc -c -Wall LeapYear.c
>gcc -LC:¥CUnit-2.1-0¥lib -o test.exe leapYear.o LeapYearTest.o -lcunit


2. ビルドと実行

ビルド
---
>gcc -IC:¥CUnit-2.1-0¥include¥CUnit -Wall -c LeapYearTest.c
>gcc -c -Wall LeapYear.c
>gcc -LC:¥CUnit-2.1-0¥lib -o test.exe leapYear.o LeapYearTest.o -lcunit
---

※ CUnit を C:¥CUnit-2.1-0 にインストールしています。


実行

実行すると、標準出力に実行結果が出ます。
これとあわせて、つぎの結果ファイルができます。
    CUnitAutomated-Results.xml 
同じフォルダに、C:¥CUnit-2.1-0¥share¥CUnit にある
    CUnit-Run.dtd
    CUnit-Run.xsl
をコピーして、CUnitAutomated-Results.xml をダブルクリックすると、IE が立ち上がり、
グラフィカルに単体テストの結果を見ることができます。


□ 実行結果
---
>test

     CUnit - A Unit testing framework for C - Version 2.1-0
     http://cunit.sourceforge.net/


Suite isLeapYear, Test testIsLeapYear001 had failures:
    1. LeapYearTest.c:35  - CU_ASSERT_EQUAL(1,isLeapYear(2000))

--Run Summary: Type      Total     Ran  Passed  Failed
               suites        1       1     n/a       0
               tests         4       4       3       1
               asserts       4       4       3       1
---



なお、すべてパスするように修正した後の実効結果は以下のようになります。
---
     CUnit - A Unit testing framework for C - Version 2.1-0
     http://cunit.sourceforge.net/

--Run Summary: Type      Total     Ran  Passed  Failed
               suites        1       1     n/a       0
               tests         4       4       4       0
               asserts       4       4       4       0
---


■ ASSERT マクロ

代表的なマクロとして、以下のようなマクロが用意されています。

    CU_ASSERT(式)
    CU_ASSERT_TRUE(式)
    CU_ASSERT_FALSE(式)
    CU_ASSERT_EQUAL(式1, 式2)
    CU_ASSERT_NOT_EQUAL(式1, 式2)
    CU_ASSERT_PTR_EQUAL(ポインタ1, ポインタ2)
    CU_ASSERT_PTR_NOT_EQUAL(ポインタ1, ポインタ2)
    CU_ASSERT_PTR_NULL(ポインタ)
    CU_ASSERT_PTR_NOT_NULL(ポインタ)
    CU_ASSERT_STRING_EQUAL(文字列1, 文字列2)
    CU_ASSERT_STRING_NOT_EQUAL(文字列1, 文字列2)
    CU_ASSERT_NSTRING_EQUAL(文字列1, 文字列2, 文字数)
    CU_ASSERT_NSTRING_NOT_EQUAL(文字列1, 文字列2, 文字数)
    CU_ASSERT_DOUBLE_EQUAL(実数1, 実数2, 精度)
    CU_ASSERT_DOUBLE_NOT_EQUAL(実数1, 実数2, 精度)
    CU_PASS(メッセージ文字列)
    CU_FAIL(メッセージ文字列)


■ 参考

CUnit
http://sourceforge.net/projects/cunit/

CUnit チュートリアル
http://homepage3.nifty.com/kaku-chan/cunit/index.html

                                                                            以上