SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

OpenCppCoverageによるカバレージの計測

  • X ポスト
  • このエントリーをはてなブックマークに追加

 カバレージを計測したいと思うことが、しばしばあります。アプリケーションやライブラリを作ったら当然ながらテストするんですが、テストの漏れ・抜けが心配になるんですよ。一連のテストのついでにカバレージを計測すればソースコードの各行が実行されたか否かが判明し、実行されなかった行があるならそこを通るテストを追加できます。お手軽なカバレージ計測ツール:OpenCppCoverageを試してみました。

  • X ポスト
  • このエントリーをはてなブックマークに追加

OpenCppCoverageとは

 アプリケーションにせよライブラリにせよ、プログラムを書いたらテストします。思ったとおりに動くことを確認するのがテストの目的ですが、テストにはいくつか弱点があります。ひとつは「それが正しいテストであることを保証できない」こと。テストはテストできませんから。そしてもうひとつは「テストに抜けがないことを保証できない」こと。前者については与えられた仕様とテストとが合致するかを確認することになります。後者はかなり厄介です。プログラム中に分岐がn個あったとすると、テストの総数は最大2^n通りになるわけで、とてもじゃないですがそれらすべてを列挙しテストに反映できる数ではありません。

 そこでテスト戦術を考えます。ひとまず考え付く限りのテストを行い、そのテストによって通過したコード上の行を緑で塗りつぶします。一連のテストを実行し、緑に塗られていない行は現テストではカバーできていないのですから、その行を通過するテストを追加します。これを繰り返し、塗り残された行がなくなれば実装したすべての行をテストによって通過した(=実行した)ことになります。正しい実装か否かは別として、少なくともテストしていない行はないことが保証されます。歯医者さんがくれる赤い染料みたいなものです。磨き残しがある箇所を探し、そこをちゃんと磨きましょう、と。

 カバレージ(網羅度)を計測するツールはLinux g++/gccなら処理系にはじめっからオマケでついてきます。コンパイル/リンク時にオプション:--coverageを付けておくとコンパイル単位ごとにファイル:~.gcnoが生成されます。どうやらこいつは生成された機械語と、それに対応するソースコードのファイル名/行番号との対応表らしい。実行すると~.gcdaが生成され、オマケのツール:gcovがgcnoとgcdaからコードの各行を通過した回数を勘定するってカラクリ。

 このgcovと同様の機能、Visual StudioではUltimateとかEnterpriseとか、かなりお高いエディションでしか提供されていないんですよ。残念なことに。

 Communityエディションにも使え、しかも無償のカバレージ・ツールがないものかと探してみたらありました。OpenCppCoverageという代物で、Visual Studioのメニュー:"拡張機能と更新プログラム"からプラグインがインストールできます。

fig-01

 マニュアルやソースコード一式はGithubから入手できます。コマンドライン版も32bit/64bitの両方あって、64bit版は32bitアプリのカバレージ計測もできるみたいです。さっそくお味見してみましょうか。

カバレージ計測対象の準備

 おためしに用意したのはちいさな関数をひとつだけ定義したDLL:calcです。足し算の繰り返しでふたつのint値の積を求めるint multiplies(int x、int y)を実装しました。

list-01 calc.h
#ifndef CALC_H__
#define CALC_H__

#ifdef CALC_IMPL
#define CALC_DLL __declspec(dllexport)
#else
#define CALC_DLL __declspec(dllimport)
#endif


#ifdef __cplusplus 
extern "C" {
#endif

CALC_DLL int multiplies(int x, int y);

#ifdef __cplusplus 
}
#endif

#endif
list-02 calc.cpp
#define CALC_IMPL
#include "calc.h"

/*
 * 加算の繰り返しによってふたつの int の積を求める
 */
CALC_DLL int multiplies(int x, int y) {
  // x回、result += y; するが そのまえに...
  // x, y それぞれ、負ならば符号反転する
  bool negative = false;
  if ( x < 0 ) { 
    negative = !negative; 
    x = -x; 
  }
  if ( y < 0 ) { 
    negative = !negative; 
    y = -y; 
  }

  int result = 0;
  /* 
   * loop回数を減らすため x > y であるときは x と y を交換する
   */
  if ( x > y ) {
    int tmp = x;
    x = y;
    y = tmp;
  }
  for ( int i = 0; i < x; ++i ) {
    result += y;
  }

  if ( negative ) {
    result = -result;
  }
  return result;
}

 Visual Studio 2017 CommunityでVisual C++ DLLプロジェクトのひな型を作り、上記calc.h/cppを追加してx64/Releaseモードでビルドしました。DLLですからdllmain()が定義されたdllmain.cppもプロジェクトに含まれています。

 次にテスト。テストは何度となく使って手慣れたgoogle testを使います。Linux g++/gccでのお仕事も少なくないのでWindows/Linuxの両方で使えるgoogle testは僕のお気に入りです。

 まずはともあれ"にさんがろく"をテストしましょう。コンソールアプリ・プロジェクト:calc_testを用意しテストをひとつ書きます。

list-03 calc_test.cpp
#include <gtest/gtest.h>
#include "calc.h"

TEST( multiplies,get_start ) {
  ASSERT_EQ(6, multiplies( 2, 3));
}
fig-02

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
OpenCppCoverageのつかいかた

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10432 2017/10/23 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング