GNU Make を単体テストのテストランナーに使用しようとして困ったことあれこれ

make test で単体テストが実行されるようになっているプロジェクトを CI/CD に対応させる際に色々と右往左往してしまったので make マスターの面々からするとヤレヤレな内容かもしれませんが… メモがてら.

ビルドシステムに make が採用されている場合、多くの場合サブディレクトリ毎に makefile が用意されていて、それをプロジェクトのトップディレクトリに置かれた makefile から再帰 make するというのがよく行われると思います.  例えば以下のような構成のプロジェクトでは (a) から (b), (c) の makefile を再帰 make すると言った具合です.

├── Makefile          — (a)
├── subdir0
│      └── Makefile  — (b)
└── subdir1
│      └── Makefile  — (c)

また、(b) (c) の makefile には疑似 ターゲットとして test が定義されており、各々のディレクトリで make test を打つことで lib の生成や単体テストのビルドと実行が行われるようになっています.  このプロジェクトを CI/CD 対応しようとしたとき、ツール側から沢山あるサブディレクトリを一つ一つ個別に叩いて行くのは面倒なので当然 (a) に定義された test ターゲットを叩いて済ませたくなる訳ですが、単体テストの実行には一般的に以下の要求事項があり、この要求を満足する形でテストランナーを実装しなくてはなりません.

(1) 途中で fail しても後続のテストは実行したい.
(2) 全てのテストを実行し終えた後に一つでも fail していた場合に全体の終了ステータスをエラーにしたい.

さてどうしたものかと言うことで、真っ先に思いついたのが for でサブディレクトリを回す方法ですが、この方法では呼び出し元の make にエラーが帰らないため、(2) の条件を満たす事ができません.

次に思いついたのが、以下のように test ターゲットのコマンド行に再帰 make を直書きして -k (–keep-going)オプションで make を起動するという方法でしたが、-k オプションはターゲットのコマンド行で発生したエラーを無視して続行するのではなく、エラーを起こしたターゲットの構築を中断して、別のターゲットの構築を続けて実行するというオプションのようなので期待した動作をしません.  (というのをやってみて気づいた)

Normally make gives up immediately in this circumstance, returning a nonzero status. However, if the ‘-k’ or ‘–keep-going’ flag is specified, make continues to consider the other prerequisites of the pending targets, remaking them if necessary, before it gives up and returns nonzero status. For example, after an error in compiling one object file, ‘make -k’ will continue compiling other object files even though it already knows that linking them will be impossible.

https://www.gnu.org/software/make/manual/html_node/Errors.html

そうこうして最終的に「サブディレクトリ毎に test_subdir0, test_subdir1 のようなテスト専用ターゲットを (a) に用意して -k オプションを付けて叩くしかない」という結論に至ったのですが、実際はディレクトリの数も多く、ベタ書きはダサいなー嫌だなーと言うことで無い知恵絞ってヒネリだしたのが以下

なんかとりとめもなくなってしまった&もっといい方法がありそうな気がしてならなですが、とりあえず要件は満たせた!??

広告

「コードの綺麗さ」と言う言葉に対する表面的な理解

「コードの綺麗さ」といった場合、いくつか評価軸がありますが恐らくほぼ以下の 3 つに集約できるのではないかと思います.

(1) 関数内部、ファイル内部等の局所的に記述されているコードの見た目 (改行とかスペースとか) が綺麗かどうか
(2) 関数内部、ファイル内部等の局所的に記述されている処理や記述に無駄なく美しいかどうか
(3) モジュールの切り分け、命名等を含む、大域的に見た設計が統一され美しいかどうか

もちろん全部綺麗なことに越した事はないですが、(3)が最も重要度と抽象度が高く、逆に(1)は個人的にそこまで重要では無いと思っています.

何故なら、見た目の統一感の無さよりアーキテクチャ上の統一感の無さの方が余程問題だから. どうしても見た目を揃えたいならツールにやらせれば良いことで、このような作業を人間が時間を割いてやるほどアホで愚かな事はありません.  (後れ馳せながら最近仕事で golang を触り始めたのですが、go fmt を処理系と一緒に用意して宗教戦争も含めた無駄を排除するという考え方、すごく良いなと思いました.)

ですが、現実にはコードの綺麗さを(1)でしか測れず、コードレビューの際にもこういった見た目の指摘ばかり繰り返す人間がかなりの割合でいます.  そういう人達に欠如しているのは、本質が何なのかを理解する能力や、コードを俯瞰してみる(つまり木ではなく森を見る)と言う視点です.

優れたソフトウェアほど一貫した設計思想があり、その思想を理解することで細部を読まずとも全体を想像し、構造を把握する事が出来ます.

自分は何度か転職をしていますが、一番最初と現在の会社を除いてこのような視点を持っている人間は皆無でした.

以前自チームで構築したプログラムを同僚に解説せよと上から仰せつかった際、全体の規模が大きかった事もありアーキテクチャーの解説を中心に行った所、「お前の説明はなっていない」と言わんばかりの感じで何故それが知りたいのか理解出来ない細部の説明ばかりを求められた事があります.

転職の際の引き継ぎだったので無表情で言われるがまま応じましたが、言うまでもなく死ぬほどウンザリしました.

残念な組織ほどこういった本質に対する理解力の欠如した人間が大きな顔をし、挙句の果てにコーディング規約なんか作っちゃってるからもう…

全ての意志決定者は一度株で大損こくべき

プログラミングとは直接関係ないですが、営利組織の舵取りに不可欠な意思決定について。

さてさて自分は投資については全くの素人なのですが、その世界ではわりと有名なプロスペクト理論(元は行動経済学の概念だそう)というのがあります。簡単に言うと

・人間は目の前の利益が手に入らないというリスクの回避を優先し、損失を目の前にすると損失そのものを回避しようとする。

と言う事だそうです。つまり、自分自身の意思決定が人間のこのような性質に影響をうけていると言うことを客観視出来ない人は、「まだまだ上がる余地があるのに上昇中の株価が反転するのが怖くて早々に売却してしまう」「値下がり中の株の含み損が売却によって確定するのを躊躇し、いたずらに損失を拡大させてしまう」という利益を上げるといった観点では逆の不合理な行動をとってしまいます。

さて、これは投資に限った話ではなく企業で行われる意思決定においても非常に似たようなケースがあるのではないでしょうか。例えば

・商談中の顧客が明らかに無理な要求をしてきているのに、失注を恐れて強気に交渉したり、切ったりすると言うことができない。
・事業がずっと赤字を垂れ流しているのに、今まで行ってきた投資を考え撤退の決断ができない。

意思決定者がこれらの責任を全面的に取ってくれれば良いのですが、残念ながらここで生じた歪は現場に降りてくるんですよねー。何故なら責任転嫁以前に自分がこのような性質にモロに流されていると言うことを彼もしくは彼女自身が認識出来ていないので、自分に非があると全く思っていないから… その挙句の、激務、長時間労働、デスマーチと言うのはもう鉄板と言っても良いぐらいお決まりな流れな気がします。

そういうのを考えると、やはり一度個人的に株で大損こいて、その理由についてきちっと消化&対策出来ている人の方が良いマネージャーや良い経営者になる可能性が高いような…

(そんなん無理やろと言うツッコミは置いておいて)少なくとも自分はそういう人の下で働きたいですね。

C++ の char, signed char, unsigned char は違う型 ?

結果から言うと char, signed char, unsigned char はそれぞれ違う種類の型です。試しに以下のコードを実行してみると結果は上から true, false, false  になります。

なぜこんな事になるかと言うと、元も子もないですが、そう規格で決まっているからです。 試しに C++14 の Working Draft を見てみますと。

3.9.1 Fundamental types

Objects declared as characters (char) shall be large enough to store any member of the implementation’s basic character set. If a character from this set is stored in a character object, the integral value of that character object is equal to the value of the single character literal form of that character. It is implementationdefined whether a char object can hold negative values. Characters can be explicitly declared unsigned or signed. Plain char, signed char, and unsigned char are three distinct types, collectively called narrow character types.

C++14 のドラフトを引用しましたが、これに関しては以前と変わっていません。

「char型が符号付きか符号無しかは処理系依存」というのは組み込み系では比較的よく知られていると思いますが (開発環境によってはどちらにするかIDE上でユーザーに設定させるものある)、 「型の種類が全く別」というのは案外認識されていないかも(?) 型を細かく分けてオーバーロードしている時とか、メタメタしたコードを書いてる時とかに意図した結果にならずにハマるかもしれませんのでメモ …

Majestouch 日本語108キー・無刻印キーキャップが発売!

キーキャップを自分で塗装して真っ黒にするか… それとも元々無刻印ラインアップのある104 配列か HHKB に乗り換えて後戻りの出来ない道に進むべきか… どうしようか悩みに悩んで、色んな誘惑に耐え、こいつの登場をどれだけ待った事か!!

Majestouch 交換用キーキャップセット 日本語108キー・無刻印

早速3セットほど予約しました。

FILCO

換装しました。

AutoHotKey を使ったなんちゃって Vi のすすめ

「タイピングが遅いデキるプログラマ」と言うのを少なくとも自分は見たことがありません。

「なんて美しい設計なんだ…」「この選択肢は以外ありえない!」というようなコードを一発で書くことが出来る天才中の天才であればいざ知らず、凡人にはやはりコードを書いて試行錯誤しながら設計をつめて行くという作業が必要不可欠です。そういった視点で考えると「いかにストレス無く快適に素早くタイピング出来るか」と言うのは良いコードを書く上ですごく重要なのではないでしょうか。

ところでタイピングする上でのストレスといえば

(1) キーボードの打鍵感の悪さ
(2) ホームポジションを崩しての移動

が結構大きな割合を占めているのではないかと個人的に思っています。

「あなたはプログラミング以外何もしなくて大丈夫です。環境もご希望のものをどうぞご自由に」と言った恵まれた職場にお勤めの方は 「HHKB」+ 「お気に入りのエディタ」で全て解決!何も思い悩む事はないのでしょうが、そうで無い場合は大人の事情 (ノーマルなキーボードも頻繁にタイプしないといけないとか、プログラマ御用達エディタ以外にも色々と使わないといけないとか、私物の周辺機器を会社の PC に接続するの禁止とか、2万円以上するキーボードを会社の経費で買いたいって!?正気か?とか… ) が絡んできて実に悩ましいところです。

でも実は (2) に関しては AutoHotKey と言うツールを使えば実質的に解決する事が出来ます。

具体的にどうするかと言いますと、殆ど無用なスペース左側の「無変換」キーとホームポジションからアクセス可能な適当なキーを組み合わせて、頻繁に使用するにも関わらずホームポジションから遠くに配置されてしまっているキーをエミュレートするのです。

跡地になってしまっていますが、元ネタはこちら  (AutoHotKey を流行らせるページ)

ちなみに、自分の場合は vi のコマンドを参考に以下のようなスクリプトを作ってカーソル移動系のキーをエミュレートしています。

vk1Dsc07B & i::Send {Home}
vk1Dsc07B & o::Send {End}
vk1Dsc07B & h::Send {Left}
vk1Dsc07B & j::Send {Down}
vk1Dsc07B & k::Send {Up}
vk1Dsc07B & l::Send {Right}

これでキーボードの打鍵感さえ我慢すれば、 どんな環境でも、どんなソフトウェアを使っての作業でも ホームポジションを崩す事無く快適にタイピングする事が可能です。(ちなみに無変換キーは左手の親指で押してます)

加えて AutoHotKey の大変便利なところが 「作成したスクリプトを付属のツールで exe 化して本体のインストールされていない PC 上でも実行する事ができる」と言う点で、USB メモリーやパブリックなネットワーク上に exe 化したスクリプトを置いておけば普段のタイピング環境をそのまま簡単に持ち出す事ができます。

null

ちなみに、情報システム部が許可したソフトウェア以外インストール禁止の会社の場合はもうぐうの音もでません…