我々は非公開の関数やメソッドをどうやって個別に単体テストするか?

前回からの続きである。

eel3.hatenablog.com

「非公開の関数やメソッドを個別に単体テストするか否か」という観点では、現状では「組み込みソフトウェア(特にファームウェア等のハードウェア寄りのもの)の開発なら有りでしょ」という見解に至ったのであった。

では次に、どうすれば非公開の関数やメソッドを個別に単体テストすることが可能となるのだろうか? 要は「どうやって実現するか?」というテクニカルな話である。

組み込み開発で定番のC言語C++を使っているならば、話は割と簡単である。プリプロセッサを悪用すればよい。

例えばソースファイルfoo.cに定義されている関数群について、テストコードをファイルtest_foo.cに書こうとしているものとする。

test_foo.cにて以下のようにプリプロセス指令を悪用することで、foo.cのファイルスコープに隠ぺいされている関数・変数・型定義などに直接アクセスすることが可能となる。

// test_foo.c

#include "foo.c"

// これ以降、foo.cのファイルスコープ中の諸々にアクセス可能!

C言語C++プリプロセッサの役割が本質的に「C/C++にチューニングされたテキスト処理」であることを理解しているならば、これがどういう詐術なのか分かるだろう。あと単体テスト用のプロジェクトの「コンパイル対象のファイル」にfoo.cを含めてはならないことも。

C++でクラスを用いていて、プライベートなメンバ変数・メンバ関数に直接アクセスしたい場合にも、もう少し悪用度を上げることで対応できる。

例えばソースファイルbar.hに定義されているクラスBarのプライベート関数を直接実行したいなら、テストコードを書くファイルtest_bar.cppにおいて:

// test_bar.cpp

#define private public
#include "bar.h"
#undef private

// これ以降、bar.hに定義されたclassのprivateな諸々にアクセス可能!

非常に乱暴な力技だが、これで何とかなる。

問題は、言語仕様に含まれる機能にてこんな無茶をできる現役のお仕事用言語がCとC++ぐらいしかない、ということである。よりモダンな言語が組み込み開発の現場に下りてきた時にどうなるのか(そもそも、そんな未来においても内部品質に踏み込んだ単体テストが必要とされるのか否か)、思案のしどころである。