FIT2009（第8回情報科学技術フォーラム）RB-006柔軟かつ複数プログラミング言語対応のテストカバレッジ測定フレームワーク

A Flexible Test-Coverage-Measurement Framework Supporting Multiple Programming
Languages
坂本 一憲 ∗

Kazunori Sakamoto1.

鷲崎 弘宜 ∗

深澤 良彰 ∗

Hironori Washizaki

Yoshiaki Fukazawaに共通する概念を用いるため，多くの言語のソフトウェア

はじめにテストにおいて利用できる．しかし，多くの測定ツールは，

テストカバレッジ（コードカバレッジ；テスト網羅率）と各言語に特化した設計になっている．そのため，各言語には，ソフトウェアテストを行う際に用いられる指標である．

対してそれぞれ測定ツールが開発されており，そういったテスト可能なプログラムの全体に対して，プログラムのソー測定ツールの新規開発，保守のコストは莫大なものとなっスコードがテストされた割合を意味する．テストカバレッている．また，上述したような複数の言語で開発されたソジは，ソフトウェアテストが十分に実行されたかどうかを

フトウェアを測定するためには，複数の測定ツールを組み判断する基準となる．

合わせる必要がある．しかし，複数の測定ツールを組み合テストカバレッジにはいくつかのレベルが存在する．例

わせると，対応するテストカバレッジレベルの差異や，実えば，すべてのステートメントにおいて，少なくとも一回装の差異による測定基準の不一致のため，テストカバレッ

以上実行されたステートメントの割合を示すステートメン

ジの有効性が失われる場合がある．

トカバレッジ (C0)，すべての条件分岐において，各分岐先

そこで我々は，複数言語対応のテストカバレッジ測定フが少なくとも一回以上実行された条件分岐の割合を示すデレームワーク（以降，提案 FW）を提案する．提案 FW でシジョンカバレッジ (C1)，すべての条件分岐の条件式を構

は言語のシンタックスに焦点を当てることで，言語間の共成する論理項において，すべての項が少なくとも一回以上

通要素の抽出と相違点の吸収を行い，特定の言語に特化しはそれぞれ真と偽の両方の値に評価された論理項の割合をた測定ツールの開発コストを低減する．さらに，新規言語

示すコンディションカバレッジ (C2) などである．テストカへの対応や機能拡張の支援を行い，複数の言語における統

バレッジレベルは，ソフトウェアテストの目的に応じて適一的で柔軟なテストカバレッジを実現する．

切なレベルが選択される [1]．

なお，研究成果である提案 FW はオープンソースとして

テストカバレッジ測定ツール（以降，測定ツール）の普及

公開しており，入手して利用できる [2]．

が進み，C 言語や Java 言語といった主要なプログラミング
言語（以降，言語）に対して，実用的な有償，無償ツールが2.

既存の測定ツールにおける問題点

提供されている．一方， COBOL 言語といったレガシーな
言語や，Lua 言語といったマイナーな言語において，測定ツールが存在していない，もしくは，高価な製品のみが提既存の測定ツールにおける問題点を以下で述べる．

2.1

新規開発コストの高さ供されている．その上，パラダイムの変化と言語の多様化が進んでおり，新しい言語への対応や，言語の仕様変更へ

多くの測定ツールは，レガシーな言語やマイナーな言語に対応していない，もしくは，対応するツールは非常に高の対応が必要とされている．
近年では，複数の言語を用いたソフトウェア開発の需要価である．例えば，我々が調査した限りでは，COBOL 言が高まっている．クライアントサーバモデルに基づいて設語に対応する無償の測定ツールが存在しなかった．さらに，計されたソフトウェアの場合，クライアントアプリケーショ

言語の多様化も進んでおり，測定ツールの新規開発に対すンとサーバアプリケーションが別々に開発される．このよる需要が高まっている．

うなアプリケーションは，それぞれ異なる言語で開発され測定ツールは，ソースコードを解析して，ソフトウェアるケースがある．そういったソフトウェアをテストする場

テストを行う際にカバレッジの情報を収集して，測定結果

合，モジュール単体をテスト対象とする単体テストでは問を表示する．測定ツールは，ソースコードから構文を解釈

題がないが，モジュールの組み合わせをテスト対象とするする構文解析器，ステートメントや条件分岐といった構文

結合テストでは，複数の言語を統一的に扱える測定ツールのセマンティクスを解釈する意味解析器，カバレッジの測が必要となる．

定機能と測定結果の表示機能から構成される．これらの機

テストカバレッジは，特定の言語に依存しない概念であ能は一般的に実装が難しく，開発に莫大なコストが必要とる．ステートメントや条件分岐といったほぼすべての言語

される．特に，測定結果の表示機能以外は，特定の言語への依存性が強く，再利用による新規開発コストの低減が困∗ 早稲田大学 大学院 基幹理工学研究科

難である．

103
（第1分冊）

FIT2009（第8回情報科学技術フォーラム）2.2

保守コストの高さ

2.5

不完全な測定の可能性

言語のパラダイム変化や機能拡張のため，言語仕様が変テストカバレッジは，ソフトウェアテストを実施した際化することがある．そして，言語仕様の変化に伴って，構に得られた情報に基づいて測定される．しかし，実行可能文の種類が増減したり構文のセマンティクスが変更される．

なバイナリファイルに対して測定する場合，ソースコード

例えば，Java 言語が 1.4 から 5.0 にバージョンアップしたと実行可能なバイナリファイルのセマンティクスの違いか際，拡張 for 文や総称型などの新しい構文と概念が言語仕様

ら，ソースコード上に存在する要素であっても，測定されに追加された [3]．

ない場合がある．

測定ツールが言語仕様の変化に対応する場合，新しい構

例えば，Java 言語の実行可能なバイナリファイルである

文に対応するため，構文解析器と意味解析器の修正が必要

クラスファイルでは，ソースコード上のどこからも呼び出であり，場合によっては，カバレッジの測定機能も修正すされない private メソッドや，常に条件式が偽となる if 文る必要がある．そのため，測定ツールの保守は必要であり，内のデッドコードは削除されることが多い．そのため，ク

そのコストは莫大なものとなる．

ラスファイルに対して測定すると，デッドコードが測定対

2.3

統一性を欠いた測定象に含まれない．

Web アプリケーションの普及などに伴って，複数の言語

Java 言語用の測定ツールである Cobertura[6] では，このを用いたソフトウェア開発が広まっている．例えば，クラ手法を用いるため，デッドコードに対する測定ができない．

イアントサーバモデルに基づいてソフトウェアを設計した
場合，クライアントアプリケーションを Python 言語で開発して，サーバアプリケーションを Java 言語で開発する

3.

カバレッジ測定フレームワークの提案

我々は，複数言語対応のカバレッジ測定フレームワーク
を提案し，上述の問題を解決，および緩和する．

ケースが考えられる．
複数の言語で開発されたソフトウェアの場合，結合テス

フレームワークは再利用可能なソフトウェアアーキテク

トにおけるカバレッジ測定が困難である．用いた言語すべ

チャであり，類似する複数のアプリケーションに対して汎てに対応したツールがなければ，複数のツールを組み合わ用的な設計を提供する．フレームワークは半完成のアプリせる必要がある．しかし，複数のツールでは測定に手間がケーションであり，開発者がアプリケーション固有のコーかかる上，対応するテストカバレッジレベルの差異や測定ドを加えることで，アプリケーションを開発できる [7]．

基準の差異の影響を受ける．そのため，ソフトウェアテス

3.1

トに対する指標として有効性が失われる場合がある．

全体の仕組み提案 FW の全体像と処理の流れを図 1 で示す．図 1 のよ

我々が調査した無償の測定ツールの中では，GNU Com-

うに，提案 FW は，コード埋め込み，コード実行，カバレッ

piler Collection のサブセットとして提供される gcov [4] 以

ジ表示の三つのサブシステムから構成される．さらに，コー

外に，複数の言語に対応したツールは存在しない．

ド埋め込みサブシステムは，AST（Abstract Syntax Tree；

2.4

柔軟性を欠いた測定

抽象構文木）生成部，AST 整形部，AST 操作部，コード生

テストカバレッジはソフトウェアテストが十分であるか

成部の四つの機能要素から構成される．

評価する有効な指標である．テストカバレッジが 100% をカバレッジ測定の流れを以下に示す．

満たすことで，ソフトウェアテストが十分であることが明確に判断できる．しかし，開発者が必要であると判断した部分
のみテストできれば，たとえテストカバレッジが 100% 未満であってもソフトウェアテストは十分である．このように，テストカバレッジは割合であり定量的な結果を示す．
そのため，100% 未満の測定結果からは，かえって定性的な判断が困難であり，必要なソフトウェアテストを完遂でき

1. ソースコードから AST の生成
2. AST を介した測定用コードの埋め込み
3. AST からソースコードの生成
4. 生成されたソースコードの実行と情報収集
5. テストカバレッジの測定結果の表示
提案 FW では測定対象のソースコードに測定用コードを埋め込み，そのプログラムを実行することでテストカバレッ

たかどうか評価することが難しい．
また，プログラム内のすべての要素を測定対象とするこジを測定する．測定用コードを埋め込む際に，ソースコーとは，効率性の面からも問題が指摘されており，測定範囲

ド中における測定対象要素の位置情報など，測定結果としを限定する必要性がある．例えば，坂田ら [5] は，コンポーて表示する際に必要となる情報も収集する．コンパイラのネントに対するカバレッジの測定において，利用する機能

最適化機能がデッドコードなどを削除する前に測定用コーのみを測定対象とする手法を提案している．

ドを埋め込むため，ソースコード上に存在する全ての要素

我々が調査した測定ツールや研究には，カバレッジ測定
範囲や測定対象要素を柔軟に指定できるものは存在しない．

を完全に測定することができる．
提案 FW の有用性を図 2 で示す．提案 FW は，オブジェ

104（第1分冊）

FIT2009（第8回情報科学技術フォーラム）図1

提案フレームワークの概観

あれば，簡単な固有コードの追加のみで対応することが可能である．
測定用コードを埋め込む操作は AST 上で行う．AST 上で埋め込むことで，各言語における埋め込み処理の相違点を減らし，共通コードとして抽出しやすくする．さらに，各言語のシンタックスに焦点を当てているため，言語仕様
図2の変化が起こった際の影響を最小限に抑える．これにより，提案フレームワークの有用性

新規開発や保守のコストを低減する．ただし，測定用コー
ドを埋め込むことで測定するという仕組み上，手続き型言
クト指向プログラミングの仕組みを用いて，オブジェクト

語のみを対象とする．

指向フレームワークとして設計されている．そのため，以測定用コードはカバレッジ情報の収集処理以外は行わな上に述べたような機能に対して，言語非依存処理に該当すい．提案 FW は，収集処理を行うという点を除いて，測定る共通コードの提供と，言語依存処理に該当する固有コード

対象のソースコードのセマンティクスが変わらないようにの実装を簡易化するための構造を提供できる．また，ソー埋め込む．そのため，ソフトウェアテストにおける振る舞

スコードの編集以外にもプラグインアーキテクチャやスクいは変化しない．

リプト言語に対応しており，固有コードの追加による機能

以下で，リスト 1 に埋め込み前，リスト 2 に埋め込み後拡張を容易にする．これにより，柔軟な測定範囲の変更や，のソースコードを示し，測定用コードの埋め込み例を示す．

特殊なカバレッジの測定を支援する．さらに，カバレッジ
リスト 1

レベル実装に関するスケルトンコードを提供することで，カバレッジレベルの種類数の統一化を促すガイドラインを

1
2

与える．現時点では，ステートメントカバレッジ，デシジョ

3
4

ンカバレッジ，コンディションカバレッジ，デシジョン／
コンディションカバレッジの四種類のカバレッジレベルへの対応を支援する．なお，パスカバレッジのようなソース
コードのセマンティクスの解析が必要なカバレッジ以外で

5
6
7
8
9
10

int main () {int a = 0;
printf ( " test " );if ( a == 0) {puts ( " a == 0 " );}else {
puts ( " a != 0 " );}}105
（第1分冊）

埋め込み前

FIT2009（第8回情報科学技術フォーラム）

リスト 2
1
2
3
4
5
6
7
8
9
10
11
12
13

AST 生成部は，ソースコードを入力して XML フォー
マットの AST を出力する．実装例では，Java 言語で埋め込み後

int main () {int a = 0;
st a te m en t _c o ve r ag e (0);printf ( " test " );if ( dec isi on _co ver age (0 , a == 0)) {s ta t em e nt _ co v er a ge (1);puts ( " a == 0 " );}else {
s ta t em e nt _ co v er a ge (2);puts ( " a != 0 " );}}は SableCC[11]，C 言語では ANTLR[12]，Python 言
語では標準ライブラリの AST 生成機能を用いて，外部プログラムとして実装する．AST 生成部はこれらの外部プログラムを呼び出すことで実装される．そのため，外部プログラムの呼び出し処理を共通コードとして Template Method パターン [13] を用いて設計しており，容易に再利用できる形で提供する．Template

例中の statement coverage サブルーチンは，ステート

Method パターンとは，抽象クラス内で自身の抽象メ

メントカバレッジの測定に，decision coverage サブルー

ソッドを呼び出す処理を定義して，処理の枠組みを決チンは，デシジョンカバレッジやコンディションカバレッ

めておき，その抽象クラスを継承した子クラスで抽象

ジの測定に利用する．decision coverage サブルーチン

メソッドを実装することで，具体的な処理内容を決定は値渡しで条件式，もしくは論理項の評価値を受け取って，するというデザインパターンである．

そのまま戻り値として返す．したがって，埋め込み前と後のコードをどちらも同じソフトウェアとしてテストできる．

4.

カバレッジ測定フレームワークの実装

提案 FW は .NET Framework 3.5 SP1[8] で実装した．
提案 FW では固有コードを追加するために以下の三つの方法に対応している．

• フレームワークのソースコードの直接編集• アセンブリファイルの作成と配置• スクリプトファイルの作成と配置

図 3 AST 生成部のクラス図

提案 FW では .NET Framework 3.5 SP1 とそれ以前のバー

AST 生成部に関連するクラスとそれらの関係を図 3 のUML[14] クラス図で示す．図 3 の AstGenerator 抽

ジョンで動作するアセンブリファイルと，Dynamic Lan-guage Runtime[9]（以降，DLR）が対応するスクリプト言語で記述したスクリプトファイルを読み込んで実行すること

象クラスが，Template Method パターンにより設計さが出来る．これは，Managed Extensibility Framework[10]れたクラスである．これを利用した例として，Java 言（以降，MEF）を用いており，提案 FW が提供するインタ

語向けの AST 生成部の固有コードをリスト 3 で示す．

フェースを実装するクラスに対して，MEF が提供する属性

リスト 3 の 15 行目の外部プログラム名と 19 行目の引を付加することで，そのクラスのインスタンス生成を自動数の指定のように，外部プログラムを呼び出すパラメー化できる．これにより，プラグインアーキテクチャを構築

タの記述のみで，簡単に実装できる．

して，アセンブリファイルやスクリプトファイルを自動的に読み込む．なお，DLR も MEF も .NET Framework 上で動作するライブラリである．

リスト 3 AstGeneratorForJava.cs
123

本節では実際に提案 FW を用いて，Java 言語，C 言語，

4
5

Python 言語に対して，ステートメントカバレッジ，デシジョンカバレッジ，コンディションカバレッジ，デシジョ
ン／コンディションカバレッジの四種類のレベルのテスト

6
7
8
9
10

カバレッジを測定するソフトウェアを実装した例を用いて，

11

提案 FW の詳細について述べる．

13

4.1

12
14
15

コード埋め込みサブシステム

16
17

コード埋め込みサブシステムは，以下で述べるような四つの機能要素によって構成される．

18
19
20
21

• AST 生成部

using System . ComponentModel . Composition ;22

namespace Cov er age F ra mew ork . AstGenerator . Java{
[ Export ( typeof ( IAstGenerator ))]public class A s t G e n e r at o r F o r J a v a : AstGenerator{
private static readonly string []_arguments = new []{" - jar " , " ../ Java / Java . jar " ,};protected override string FileName{
get { return " java " ; }}protected override string [] Arguments{
get { return _arguments ; }
}
}
}

106
（第1分冊）

FIT2009（第8回情報科学技術フォーラム）• AST 整形部
AST 整形部は，AST を AST 操作部で操作しやすいよ

リスト 4 AtomicBooleanTermSelectorForPython.cs
1
2

うに変形する．

3

実装例では入力された AST の不要なノードの削除や新

4

たなノードの追加を行う．具体的には，子要素として

6

非終端記号を一つだけ持つ非終端記号を削除する処理，

8

一行で記述可能な if 文の省略形などを完全な形に変形

10

5
7
9
11

する処理である．前者は共通コードとして完全に提供されるが，後者は if 文の省略形の特定と変形方法を固有コードとして実装する必要がある．なお，そのコー

12
13
14
15
16
17

ドは AST 操作部を用いて容易に実装できる．

18• AST 操作部

19
20

AST 操作部は，様々な機能の集合体である．具体的には，AST が木構造であることを利用して，部分木を列挙する機能，部分木を生成する機能，AST 中の部分木

21
22
23
24
25

using System . Linq ;using System . Xml . Linq ;using System . ComponentModel . Composition ;namespace Cov er age F ra mew ork . Element . Selector . Python{[ Export ( typeof ( IX Ele m e ntS ele cto r ))]public class A t o m i c B o o l e a n T e r m S e l e c t o r F o r P y t h o n: AtomicBooleanTermSelector{
private static readonly string []_ c o n d C o m p o n e n t N a m e s = new []{" or_test " , " and_test " ,};private static readonly string []_condNames = new []{" or_test " , " and_test " ,};private static readonly string []_condOpValues = new []{" or " , " and " ,};26を入力として新たな部分木に置換する機能がある．

28

protected override bool
Is B o o l T e rm S ep a rt o r ( XElement e )

29

{

27

部分木を列挙する機能は，測定用コードの埋め込み位置の特定に利用する．例えば，Python 言語でコンディ
ションカバレッジの測定を実現するために，条件式をreturn ! e . HasElements &&_condOpValues . Contains ( e . Value );

30
31

}
protected override bool
I s C o n d i t i o n a l E x p r e s s i o n ( XElement e ){return _condNames . Contains ( e . Name . LocalName );}protected override bool
I s C o n d i t i o n a l E x p r e s s i o n C o m p o n e n t ( XElement e ){return _ c o nd C o m p o n e n t N a m e s. Contains ( e . Name . LocalName );
}

32
33

構成する論理演算子に注目して分解したすべての項に34

対して，測定用コードを埋め込む．そのためには，条件36式に対応する部分木の中から，各論理項に対応する部

38

分木を列挙する処理が必要である．この処理は言語非

40

35
37
39
41

依存であるため，Template Method パターンによって42
43

設計した共通処理の実装を提供する．

}

44
45

}

その他にも，複数の列挙結果を一つの列挙結果にまとめる XElementSelectorUnion クラスや，列挙結果の中からさらに列挙を行う XElementSelectorPipe
ク ラ ス な ど ，様 々 な 処 理 を 提 供 す る ．こ れ ら は ，Command パターン [13] によって設計されており，
IXElementSelector インタフェースを実装したクラスのインスタンスを組み合わせて，新しい処理を行う機能を実現できる．なお，Command パターンとは，処理要求とそれに伴うパラメータをカプセル化してイ
図 4 AST 生成部のクラス図

ンスタンスで表現するデザインパターンである．特に，

Command にあたるインスタンスを組み合わせて作っこの処理に関係するクラス図を図 4 で示す．図 4 のたインスタンスを Macro Command と呼ぶ．

AtomicBooleanTermSelector 抽象クラスが，Template Method パターンにより設計されたクラスである．これを利用した例として，Python 言語向けの論理項を列挙する固有コードをリスト 4 で示す．リスト 4の 27 行目のノードが論理演算子かどうかを判定する
メソッド，33 行目の条件式かどうかを判定するメソッ
ド，38 行目の論理項かどうかを判定するメソッドのよ
うに，与えられたノードが測定対象であるかどうかを判定する処理を記述するだけで，簡単に実装できる．

107（第1分冊）

図5

部分木の列挙に関係するクラス図

FIT2009（第8回情報科学技術フォーラム）部分木の列挙に関係するクラス図を図 5 で示す．図5 の XElementSelectorPipe クラスが Command パ
ターンによって設計されたクラスである．このクラス
は，Macro Command に相当しており，複数の Com-

mand インスタンスを組み合わせて新たに一つの処理を表現する．これを利用した例として，条件文に対応する部分木の列挙処理を表す IfSelectorForC クラスのインスタンスと，括弧で括られたコードに対応する部分木の列挙処理を表す ParenthesisSelectorForC
クラスのインスタンスを組み合わせて，C 言語向けの
条件式に対応する部分木の列挙処理を表すコード断片

図6

コード生成に関係するクラス図

をリスト 5 で示す．
リスト 5 XElementSelectorPipe の使用例
1
2
3

リスト 6

var ifSelector = new X E l e m e n t S e l e c t o r P i p e (new IfSelectorForC () ,new P a r e n t h e s i s S e l e c t o r F o r C ());

1
2

SourceCodeGeneratorForPython.cs

using System . Xml . Linq ;using System . ComponentModel . Composition ;3
45

リスト 5 では，二種類のクラスのインスタンスを与え67ることで，条件式を列挙するインスタンスを作成して8いる．このように，処理の粒度を小さくして，プログラ

10

ムの部品化と再利用を促進する．また，このようにし

9
11
12

て部分木の特定の処理を記述することで，柔軟な測定13を実現する．

15

なお，部分木を生成する機能は，測定コードに対応する

17

部分木の生成に利用される．この機能は固有コードと

19

14
16
18
20

して実装しなければならない．一方，部分木を置換す

21
22

る機能は，測定コードに対応する部分木を AST に埋め込むために利用される．この機能は共通コードとして

23
24
25
26

完全に提供される．

27• コード生成部

2829

コード生成部は，AST から各言語のソースコードを出

30

namespace Cov er age F ra mew ork . CodeGenerator . Python{[ Export ( typeof ( I S o u r c e C o d e G e n e r a t o r ))]public class S o u r c e C o d e G e n e r a t o r F o r P y t h o n: S o u r c e C o d e G e n e r a t or{protected override bool
T re a t T e r m i n a l S y m b o l ( XElement element ){switch ( element . Name . LocalName ){case " NEWLINE " :WriteLine ();break ;
case " INDENT " :Depth ++;
break ;
case " DEDENT " :Depth - -;break ;
default :return false ;}return true ;}}}力する．AST の設計次第ではあるが，各終端ノードがソースコード内のすべてのトークンを属性として記憶

4.2

コード実行サブシステム

している場合，トークンをそのまま出力するだけで良コード実行サブシステムは，測定用コードを埋め込んだ

く，各言語間の処理内容にほとんど差異はない．そのたプログラムを実行する．提案 FW は，コードを実行する処

め，提案 FW では Template Method パターンによっ

理系に関する制約がないため，任意の処理系で実行できる．

て設計された共通処理の実装を提供する．

測定用コードを埋め込んだプログラムを実行することで，コード生成部に関係するクラス図を図 6 で示す．図得られた情報をカバレッジ表示サブシステムに送信する．

6 の SourceCodeGenerator 抽象クラスが，Template
Method パターンにより設計されたクラスである．これを利用した例として，Python 言語向けのコード生成

送信の仕組みとして，ソケットによる TCP/IP 通信と，ファ部の固有コードをリスト 6 で示す．Python 言語向けの AST の終端ノードでは改行とインデントを属性として記憶していないため，それらを表す終端ノードに対して，別途改行とインデントの出力が必要となる．リスト 6 の 13 から 27 行目までのように，終端ノードに対する例外的な処理を記述するだけで，簡単に実装できる．

イル出力の二種類を提供する．

4.3

カバレッジ表示サブシステム

カバレッジ表示サブシステムでは，測定用コードを埋め込む際に得られた情報と，コード実行サブシステムから受信した情報を解析して，測定結果を表示する．
測定用コードを埋め込む際に得られた情報は，位置情報とタグを含む．位置情報は，ソースコードのファイルシス
テム上のパスと，測定対象要素のソースコードにおける位置を示ために行番号と列番号を持つ．タグは，階層構造を

108（第1分冊）

FIT2009（第8回情報科学技術フォーラム）表す文字列であり，集計したテストカバレッジの結果を表る測定ツールにおける，測定用コードを埋め込む処理に関す示する際に，フィルタリングを可能にする．例えば，タグるコードの LOC の比較結果を図 8 で示す．図 8 のように，

で名前空間やクラス階層を表現することで，特定の名前空Java 言語に対応する既存ツールの Cobertura では 1056 行

間やクラス階層のみの結果に限定できる．

で，提案 FW を用いた実装例の Java 言語特有の埋め込みに

測定結果は，位置情報を利用して，測定対象要素がソフ関する部分では 215 行である．なお，Cobertura では実行

トウェアテストの際に実行されたかどうかと，ソースコー

可能なバイナリ形式のクラスファイルに対してコードを埋ドにおいてどこに位置するかを示す．

め込むため，BCEL[16] というライブラリを利用している．
しかし，実装例では自作した簡単なヘルパメソッドや標準ライブラリを利用しているが，それ以外のライブラリを一切使用していない．一方，Python 言語に対応する既存ツー
ルの Statement coverage for Python では 131 行で，提案

FW を用いた実装例の Python 言語特有の埋め込みに関する部分では 153 行である．Statement coverage for Python
では Python の標準ライブラリを利用している．なお，提案 FW の測定用コードを埋め込む処理に関する共通コードのコード行数は 654 行である．
図7

カバレッジ表示サブシステム

カバレッジ表示サブシステムの表示画面を図 7 で示す．
上部のプログレスバーがカバレッジの割合を示しており，中央部のテキストでは，各測定対象要素について，ソフトウェ
アテストの際に実行されたかどうかの○×とともに，ソースコードにおける位置を行と列で表す．

評価

5.

代表的な測定ツールと比較して，提案 FW の評価を行う．Java 言語では Cobertura，Python 言語では Statement

coverage for Python[15] を比較対象とする．

5.1

図9

新規開発コストの低減

対応カバレッジレベル数

測定ツールにおける測定用コードを埋め込む処理に関する部分の LOC (Lines Of Code; コード行数) とカバレッジ

Java 言語に対応する測定ツールと Python 言語に対応すレベルの種類数を比較して，新規開発コストを評価する．

る測定ツールにおける，対応するカバレッジレベルの種類
数の比較結果を図 9 で示す．図 9 のように，Cobertura はステートメントカバレッジとデシジョンカバレッジの二種類で，Statement coverage for Python はステートメントカ
バレッジの一種類にのみ対応している．一方，提案 FW を用いた実装例では，ステートメントカバレッジ，デシジョ
ンカバレッジ，コンディションカバレッジ，デシジョン／
コンディションカバレッジの四種類に対応している．したがって，既存ツールより多機能であるのにも関わらず，少ないコード行数で実装が可能となっている．
提案 FW では図 1 で示されるコード埋め込みサブシス
テムの一部を実装するだけで，新しい言語に対応した測定ツールを開発できる．一方，提案 FW を用いずに新たに開図8

測定コードの埋め込み処理に関する部分のコード行数

発する場合は，全てのサブシステムに該当するものを開発する必要がある．さらに，コード埋め込みサブシステムのJava 言語に対応する測定ツールと Python 言語に対応す部分のみを比較しても，上述の比較結果のように，複数言

109（第1分冊）

FIT2009（第8回情報科学技術フォーラム）語への対応を前提とした場合，提案 FW を用いた方が実装

定かを選ばざるを得ない．そのため，テストの指標としてに必要なコード行数の総量が少なくなる．

不十分なテストカバレッジしか得られない可能性がある．
一方，提案 FW を用いた場合，それぞれのプログラムに以上から，新規開発コストの問題の緩和に成功した．

5.2

対して，測定基準の差異がない同じレベルのテストカバレッ

保守コストの低減

ジを測定できる．そのため，テストの指標として有効なテ

言語仕様の変更に伴って必要となる修正について議論すストカバレッジが得られる．

ることで，保守コストを評価する．

以上から，複数の言語を用いたソフトウェアのカバレッ

言語仕様の変更に伴う修正コストについて評価を行う．

ジ測定における問題の解決に成功した．

Cobertura では BCEL というライブラリを用いてクラス

5.4

ファイルの操作を行っているが，クラスファイルの仕様が変更された場合，BCEL がその変更に対応するまで待つか，

柔軟な測定

カバレッジ測定範囲のカスタマイズについて議論するこもしくは独自にライブラリを修正しなければならない．一とで，柔軟な測定を評価する．

方，提案 FW では言語のシンタックスに焦点を当てている

Cobertura も Statement coverage for Python もカバレ

ため，測定対象要素の特定と測定コードの埋め込みが可能

ッジ測定範囲をカスタマイズできない．Cobertura はパッでさえあれば正常に動作する．そのため，図 1 で示される

ケージ，クラス，メソッドといった階層による限定は可能

AST 操作部の一部を修正するだけで済む，もしくは，修正であるが，例えば，特定のメソッドを呼び出すステートメ

が不要な場合もある．

ントのみに限定するといったことは不可能である．

Java 言語が 1.4 から 5.0 にバージョンアップした場合を例に取ると，提案 FW では，AST 操作部に拡張 for 文に対用コードを埋め込む位置を自由に調整できる．これにより，応する AST 上の部分木の列挙処理を追加するだけで良い．

特定のメソッドを呼び出すステートメントのみを指定して，

一方，Cobertura では，拡張 for 文以外にもジェネリクス

ステートメントカバレッジを測定するためのコードを埋めなど全ての言語仕様の変化に BCEL が対応した上で，拡張込むことができる．このような測定用コードを埋め込んだfor 文に対する埋め込み処理を追加する必要がある．したがって，提案 FW は修正する範囲を低減して，コストを削プログラムを実行すれば，特定のメソッドを呼び出すステー

一方，提案 FW では固有コードを追加することで，測定トメントのみに限定した特殊なステートメントカバレッジ

減できる．ただし，構文解析器は提案 FW でも Coberturaが得られる．なお，MEF によるプラグインアーキテクチャ

でも，コンパイラコンパイラを用いて実装しているため，や DLR によるスクリプト言語への対応により，容易に固有

保守コストに差異は無い．なお，コンパイラコンパイラとコードを追加できる．

は構文解析器のソースコードを自動生成するためのソフト

以上から，柔軟なカバレッジ測定における問題の解決にウェアである．また，カバレッジ結果の集計や表示に関し成功した．

ては，どちらも修正が不要である．

5.5以上から，測定ツール全体における保守コストの問題のデッドコードの測定について議論することで，完全な測緩和に成功した．

5.3

完全な測定

定を評価する．

統一的な測定Cobertura は，クラスファイルに測定用コードを埋め込

複数の言語で開発されたソフトウェアにおけるカバレッ

む．しかし，クラスファイルはコンパイラの最適化によっ

ジ測定について議論することで，統一的な測定を評価する．

てデッドコードが失われており，デッドコードに対して測Java 言語で実装したサーバアプリケーションと，Python

定用コードを埋め込むことができない．

言語で実装したクライアントアプリケーションの両方を稼

一方，提案 FW では，コンパイラが最適化を行う前に，働して結合テストを行う場合，サーバアプリケーションのソースコードに測定用コードを埋め込む．そのため，コンカバレッジ測定に Cobertura を用いて，クライアントアプ

パイラの最適化によってデッドコードが失われたとしても，

リケーションのカバレッジ測定に Statement coverage for

埋め込み時の情報として残り，カバレッジされなかった部

Python を用いるとする．しかし，Cobertura ではステート分として判断できる．

メントカバレッジとデシジョンカバレッジを測定できるが，Statement coverage for Python ではステートメントカバ
レッジしか測定できない．Python 言語において，デシジョ

リスト 7
1
2

ンカバレッジを測定できる無償ツールは，我々が探した範囲内では存在しなかった．この場合，それぞれのプログラ
ムに対する異なったレベルのテストカバレッジ測定か，もしくは，同じレベルであるステートメントカバレッジの測

3
4
5
6
7
8

DeadCode.java

public class DeadCode {public static void main ( String [] args ) {System . out . println ( " main " );if ( false ) {System . out . println ( " deadcode " );
}
}
}

110
（第1分冊）

FIT2009（第8回情報科学技術フォーラム）リスト 7 に，デッドコードを含むソースコード例を示す．

とで，測定ツールを開発する手法を提案している．

このソースコードを Cobertura でテストすると，ステート

桐井らの手法では，カバレッジレベルについて，ステー

メントカバレッジが 100% になるが，提案 FW の実装例でトメントカバレッジとデシジョンカバレッジ以外に，測定すると，ステートメントカバレッジが 50% となる．こRC0 というレベルに対応している．RC0 とはプログラのように，デッドコードの検出にも役立てることができる．

ムを修正した際に，修正した差分のみを測定対象とし以上から，コンパイラの影響による不完全な測定の問題

たステートメントカバレッジのことである．

の解決に成功した．

5.6

しかし，埋め込み方法としては，ステートメントの挿
入のみによってカバレッジを測定しており，ステート

実行効率

メントカバレッジとデシジョンカバレッジの二種類

カバレッジを測定するためにテストした際の実行時間をのみに対応する．また，Java，C/C++，VisualBasic，

比較して，時間効率を評価する．
測定ツールは，テスト時にカバレッジ測定を行うためパ

ABAP/4 の四種類の言語に対応しているが，それぞれフォーマンス低下を引き起こす．ソースコードに測定用の共通処理などには言及しておらず，新たに対応する

コードを埋め込む手法では，埋め込んだコードの実行によ

言語を増やす際の支援はない．

りパフォーマンスが低下する．

一方，提案 FW における実装例では，RC0 に対応していないが，機能拡張と柔軟な測定の支援により，RC0 を

実際に，Cobertura と提案 FW の実装例とで，書籍から引用した三種類の Java プログラム [17] に対してカバレッジを測定しながらテストを行い，実行時間を測定した．

含め，新たなカバレッジレベルへの対応が可能である．

• Hridesh Rajan らは，AspectJ などのアスペクト指向言語で使われるポイントカットの記述方法を応用して，測定対象の指定手法を提案している．

Hridesh Rajan らの手法では，C#言語に対応する測定ツールの実装例が示されている．例えば，メソッド呼
び出し，if 文，foreach 文，例外ハンドラ，代入文など
様々な測定対象を指定して，測定範囲を限定できる．
しかし，測定対象を指定する記述モデルは，C#言語に特化しており，C#言語とパラダイムの異なる言語には，記述モデルを利用できない可能性が高い．
一方，提案 FW では，機能拡張と柔軟な測定により，Hridesh Rajan らの記述モデルを言語非依存に修正した上で，測定対象の指定方法として実装できる．
図 10• その他，三宅ら [20] は複数のプログラミング言語に対実行時間応したメトリクス計測プラグインプラットフォームを提案している．三宅らの手法は，AST を介することで図 10 のように，提案 FW では，同一 PC 内でソケット複数のプログラミング言語に対応しており，本手法とによる TCP/IP 通信を用いることで，元のソースコード

目的が異なるものの，類似性が見られる．

と比較して，2 倍から 10 倍程度の実行時間に抑えており，また，嶋野ら [21] はシェルスクリプトを XML フォー

Cobertura と比較して 10 倍程度早くなっている．ただし，

マットで表現することで，シェルの違いによる文法のファイル出力を用いた場合は，元のソースコードと比較し差を吸収する手法を提案している．嶋野らの手法は，て 1000 倍以上，Cobertura と比較して 10 倍から 30 倍程

木構造である XML フォーマットを用いる点で，本手度遅くなっている．そのため，素朴なファイル出力よりも，法との類似性が見られる．

TCP/IP 通信の方が圧倒的に高速であることが分かる．
以上により，ソケットによる TCP/IP 通信を用いること
で，ソフトウェアテストにおける実行効率の低下の問題が

7.

まとめと展望ないことを確認した．

本稿では，多言語対応のカバレッジ測定フレームワーク

関連研究を提案した．これにより，共通処理の再利用により開発コ

6.

提案 FW の仕組みや目的に関連する研究として，桐井ら[18] の手法と，Hridesh Rajan ら [19] の手法がある．

ストの低減，複数の言語に統一的に対応したカバレッジ測定，機能拡張の支援による柔軟な測定，ソースコードへの埋め込みによる完全な測定をした．

• 桐井らは，ソースコードに測定用コードを埋め込むこ以降，今後の展望について，考えられる改良点を述べる．

111（第1分冊）

FIT2009（第8回情報科学技術フォーラム）1. 対応テストカバレッジの種類の拡大
マルチプルコンディションカバレッジや桐井らの手法
による差分のみを測定対象とするカバレッジなど，様々
なカバレッジに対応することが考えられる．

2. カバレッジ測定用コードの実装支援
測定用コードに対応する AST 上における部分木の生成処理に関して，必要となる部分木そのものを開発者が導き出してから実装する．これに対して，測定用コー
ドの埋め込み前と埋め込み後のコードの差分から，必要となる部分木を提案 FW が導き出すことで，生成処理の実装を半自動化する支援が考えられる．
また，埋め込んだ測定用コードを AST 上の操作対象にしない場合，測定用コードを部分木ではなく，ただの文
字列トークンとして埋め込んでも良い．そのため，測定用コードに対する AST 上の操作を想定しなければ，部分木を生成する処理の実装を大幅に簡略化できる．

3. カバレッジ測定用コード本体の実装支援
測定用コードが呼び出すサブルーチン本体の実装への支援が必要である．C/C++ で記述されたプログラ
ムやライブラリを様々な言語から呼び出せるように，
インタフェース部分のコードを自動生成する SWIG

(Simplified Wrapper and Interface Generator)[22] というソフトウェアがある．これを利用することで，サブルーチン本体の実装の手間を省くことができる．

4. カバレッジ表示サブシステムの改良
Java 言語におけるパッケージ，クラス，メソッドといった階層情報をタグ情報に含めて，測定結果を階層情報でフィルタリングする改良が考えられる．
また，プロファイリングツールとしての応用が考えられる．測定対象要素の実行回数を取得できるため，例
えば，各ステートメントや条件分岐における各分岐先の実行回数を表示できる．

Software Engineering Conference (APSECIEEE CS, pp.79-86, 2006.

06),[6] Cobertura, http://cobertura.sourceforge.net/.
[7] Mohamed Fayad and Douglas C. Schmidt, ”ObjectOriented Application Frameworks”, the Communications of the ACM, Special Issue on ObjectOriented Application Frameworks, Vol. 40, No. 10,
October 1997.
[8] Microsoft, .NET Framework,
http://msdn.microsoft.com/netframework/.
[9] Microsoft, Dynamic Language Runtime,
http://dlr.codeplex.com/.
[10] Microsoft, Managed Extensibility Framework,
http://www.codeplex.com/MEF/.
[11] Etienne M. Gagnon, Ben Menking, Mariusz
Nowostawski, Komivi Kevin Agbakpem and Kis
Gergely, SableCC, http://sablecc.org/.
[12] ANTLR, http://www.antlr.org/.
[13] E. Gamma, R. Helm, R. Johnson and J. Vlissides.
”Design Patterns: Elements of Reusable ObjectOriented Software”, Addison-Wesley, 1994.
[14] OMG, Unified Modeling Language (UML) specification, version 2.2, http://www.omg.org/spec/UML/.
[15] Gareth Rees, Statement coverage for Python,
http://garethrees.org/2001/12/04/
python-coverage/.
[16] Apache Software Foundation, The Byte Code Engineering Library,
http://jakarta.apache.org/bcel/.
[17] 奥村晴彦, 杉浦方紀, 津留和生, 首藤一幸, 土村展之著,”Java によるアルゴリズム事典,”, 技術評論社, 2003.
[18] 桐井隆志, 三好辰弥, 岸上諭, 大里立夫, 曽根原勝, ”
ソースコード埋め込み型カバレッジツールについて”,
情報処理学会第 65 回全国大会, 2003.

参考文献[19] Hridesh Rajan and Kevin Sullivan, ”Aspect Lan-

[1] Lee Copeland, ”A Practitioner’s Guide to Software
Test Design”, Artech House, 2003.
[2] 坂本一憲, Open Code Coverage Framework,
http://sourceforge.jp/projects/codecoverage/.
[3] Sun Microsystems, J2SE(TM) 5.0 New Features,
http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html.
[4] the GNU Compiler Collection,
http://gcc.gnu.org/.

guage Features for Concern Coverage Profiling”, International Conference on Aspect-Oriented Software
Development (AOSD’05), pp181-191, 2005.
[20] 三宅達也, 肥後芳樹, 井上克郎, ”メトリクス計測プラグ
インプラットフォーム MASU の開発”, ソフトウェア
エンジニアリングシンポジウム 2008, pp63-70, 2008.

[21] 嶋野淳子, 新家博文, 四野見秀明, ”シェルスクリプトのための XML モデル”, 情報処理学会 ソフトウェア工学[5] Yuji Sakata, Kazutoshi Yokoyama, Hironori
Washizaki and Yoshiaki Fukazawa, ”A precise estimation technique for test coverage of components

研究会, Vol.2008, No.29, pp211-218, 2008.
[22] Simplified Wrapper and Interface Generator,

http://www.swig.org/.

in object-oriented frameworks”, 13th Asia-Pacific112（第1分冊）