連載
» 2007年09月14日 00時00分 公開

連載 C++開発者のための単体テスト入門:第3回 C++アプリケーションの効率的なテスト手法(NUnit編) (3/4)

[επιστημη(えぴすてーめー),著]

■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

Counterクラスのヘッダ・ファイル(Counter.h)

#include "Counter.h"

Counter::Counter() {
}

int Counter::get() const {
  return -123;
}

void Counter::incr() {
}

void Counter::clear() {
}

Counterクラスのソース・ファイル(Counter.cpp)

 次にこの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();
};

Counterクラスをテストするコードが実装されたヘッダ・ファイル(CounterTest.h)

#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));
}

Counterクラスをテストするコードが実装されたソース・ファイル(CounterTest.cpp)

 この例ではヘッダと実装を分離していますが、以下のように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));
}

};

Counterクラスのテスト・コードを一本化したソース・ファイル(CounterTest.cpp)

 以上のコードでソリューションをビルドしましよう。

C++ネイティブ・コードのテスト:テストの実行

 ビルドできたら、NUnitテストランナーを起動し、「CounterTest.dll」を開いて「Run」してください。前述のC#と同様、Counter.cppファイルに修正を加え、CounterTestをビルドしてRunを繰り返し、全テストに成功すればCounterクラスの出来上がりです。

CounterTest.dllのすべてのテストが成功した例

 次のページでNUnitを使ったテストの制限について紹介します。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。