第3回 C++アプリケーションの効率的なテスト手法(NUnit編):連載 C++開発者のための単体テスト入門(3/4 ページ)
C++のネイティブ・コードも.NETコードも同じように単体テストしたい!? それならNUnitが便利だ。そのテスト方法を紹介。
■C++ネイティブ・コードをテストする
●C++ネイティブ・コードのテスト:テスト対象の作成
テスト対象は前回のCppUnitの説明で使ったものと同じCounterクラスです。先ほどのソリューション内にVisual C++のスタティック・ライブラリ・プロジェクト「Counter」を作り、Counter.hおよび(ハリボテの)Counter.cppファイルを実装します。念のため、以下にコードを再掲しておきます。
#ifndef COUNTER_H__
#define COUNTER_H__
class Counter {
private:
// プライベート変数
int count_; // カウント値(=int型の変数)を内包する
public:
// コンストラクタ
Counter(); // カウント値の初期値は「0」である
// メソッド
int get() const; // 現在のカウント値を返す
void incr(); // カウント値を+1する
void clear(); // カウント値を初期値(=0)に設定する
};
#endif
#include "Counter.h"
Counter::Counter() {
}
int Counter::get() const {
return -123;
}
void Counter::incr() {
}
void Counter::clear() {
}
次にこのCounterクラスに対するテスト・コードをC++/CLIで実装します。
●C++ネイティブ・コードのテスト:テストの作成
ソリューションにVisual C++のCLRクラス・ライブラリのプロジェクト「CounterTest」を追加します。
CounterTestプロジェクトの依存関係とインクルード・ディレクトリ、ならびにNUnitへの参照を設定します。
CounterTestプロジェクトにおける依存関係の設定
[ソリューション エクスプローラ]でCounterTestプロジェクトの項目を右クリックして、開かれるコンテキスト・メニューから[プロジェクト依存関係]を選択する。これにより、この画面のような[プロジェクトの依存関係]が表示されるので、[依存先]の「Counter」にチェックを入れて[OK]ボタンをクリックする。
CounterTestプロジェクトにおけるインクルード・ディレクトリの設定
[ソリューション エクスプローラ]でCounterTestプロジェクトの項目を右クリックして、コンテキスト・メニューから[プロパティ]を選択。これにより、この画面のような[CounterTest プロパティ ページ]が表示されるので、[構成プロパティ]−[C/C++]−[全般]を選択し、[追加のインクルード ディレクトリ]に「../Counter」を入力して[OK]ボタンをクリックする。
CounterTestプロジェクトにおけるNUnitへの参照の設定
先ほどと同じように[CounterTest プロパティ ページ]を開き、[共通プロパティ]−[参照設定]を選択し、[新しい参照の追加]ボタンをクリックして「nunit.framework」アセンブリを追加し、[OK]ボタンをクリックする。
以上の準備が終わったら、CounterTestプロジェクトの「CounterTest.h」と「CounterTest.cpp」ファイルにテスト・コードを実装します(※このコードは前回のCppUnitと内容が異なります)。付記する属性はC#と同じです。
#pragma once
using namespace System;
using namespace NUnit::Framework;
using namespace NUnit::Framework::SyntaxHelpers;
#include "Counter.h"
// 以下はCounterTestクラスの宣言-----
[TestFixture]
public ref class CounterTest : AssertionHelper {
private:
Counter* c_;
public:
[SetUp] void setUp();
[TearDown] void tearDown();
[Test] void test_init();
[Test] void test_incr();
[Test] void test_clear();
};
#include "stdafx.h"
#include "CounterTest.h"
// warning(警告)表示の抑止のため、0の代わりにzeroを用いる
#define zero safe_cast<Object^>(0)
// 各テスト・ケースの実行直前に呼ばれる
void CounterTest::setUp() {
c_ = new Counter();
}
// 各テスト・ケースの実行直後に呼ばれる
void CounterTest::tearDown() {
delete c_;
}
// これ以降はテスト・ケースの実装内容
void CounterTest::test_init() {
Expect(c_->get(), EqualTo(zero));
}
void CounterTest::test_incr() {
for ( int i = 1; i < 10; ++i ) {
c_->incr();
Expect(c_->get(), EqualTo(i));
}
}
void CounterTest::test_clear() {
c_->incr();
c_->incr();
c_->clear();
Expect(c_->get(), EqualTo(zero));
}
この例ではヘッダと実装を分離していますが、以下のようにCounterTest.cpp一本にまとめてもかまいません。
using namespace System;
using namespace NUnit::Framework;
using namespace NUnit::Framework::SyntaxHelpers;
#include "Counter.h"
#define zero safe_cast<Object^>(0)
// 以下はCounterTestクラスの宣言-----
[TestFixture]
public ref class CounterTest : AssertionHelper {
private:
Counter* c_;
public:
[SetUp] void setUp() { c_ = new Counter(); }
[TearDown] void tearDown() { delete c_; }
[Test] void test_init() {
Expect(c_->get(), EqualTo(zero));
}
[Test] void test_incr() {
for ( int i = 1; i < 10; ++i ) {
c_->incr();
Expect(c_->get(), EqualTo(i));
}
}
[Test] void test_clear(){
c_->incr();
c_->incr();
c_->clear();
Expect(c_->get(), EqualTo(zero));
}
};
以上のコードでソリューションをビルドしましよう。
●C++ネイティブ・コードのテスト:テストの実行
ビルドできたら、NUnitテストランナーを起動し、「CounterTest.dll」を開いて「Run」してください。前述のC#と同様、Counter.cppファイルに修正を加え、CounterTestをビルドしてRunを繰り返し、全テストに成功すればCounterクラスの出来上がりです。
次のページでNUnitを使ったテストの制限について紹介します。
Copyright© Digital Advantage Corp. All Rights Reserved.