💯

[Swift] コードカバレッジをXcodeを使わずに確認する

2020/12/04に公開

普通に「Swift コードカバレッジ」で検索するとXcodeでコードカバレッジを有効にする方法しか出てきませんが、もちろんswiftコマンドでもコードカバレッジを計測できます。

コードカバレッジを有効にしてテストする

テストしたいSwift Packageでswift test --enable-code-coverageと打つだけです。そういえばSwiftコマンドはswift package completion-tool generate-YOURSHELL-scriptで補完を生成できるのですが、あまり知られていない気がします。

しかしこのオプションをつけて実行しても標準出力はただのswift testとなんら変わりません。一体生成物はどこにあるのでしょうか?

結果を確認する

まあ普通に「Swift test --enable-code-coverage」と検索すれば世の中には先人というものがぎょーさんおる訳です。日本語の記事はなさそうだったのでインターネットの民として情報を複製していきましょう。

llvmを入れる(てもいい)

Linuxとかだと(多分)ないので入れる必要があります。Macでは(Xcodeを入れていると?)xcrun llvm-covllvm-covを呼べるので次章以降適宜代用してください。

brewだとかaptを使って適当に入れて、

export PATH="/usr/local/opt/llvm/bin:$PATH"

をzshrcにでも書いてパスを通しましょう。

llvm-cov report

このコマンドを実行するだけです。もちろんmyProjectPackageTestsは適当にテストターゲットの名前を入れてください。

llvm-cov report \
  .build/x86_64-apple-macosx/debug/myProjectPackageTests.xctest/Contents/MacOS/myProjectPackageTests \
  -instr-profile=.build/x86_64-apple-macosx/debug/codecov/default.profdata \
  -ignore-filename-regex=".build|Tests" \
  -use-color

色付きで結構見やすく表示されましたね。

llvm-cov show

次にどこがテストされてるかを確認しましょう。

llvm-cov report \
  .build/x86_64-apple-macosx/debug/myProjectPackageTests.xctest/Contents/MacOS/myProjectPackageTests \
  -instr-profile=.build/x86_64-apple-macosx/debug/codecov/default.profdata \
  -use-color

-instr-profileオプションより後ろにソースコードを指定することで特定のファイルのみを見ることもできます。

適当にシェルスクリプトに

8割コピペですが。find-root-pathというのはSources等にいるときでも呼べるようにPackage.swiftのあるパスを取得するコマンドです。

swift-cov-report

#!/bin/env sh

PACKAGE_PATH=`find-root-path Package.swift`

if [[ -z $PACKAGE_PATH ]]; then
	echo "$(pwd) is not swift package"
	exit 1
fi

BIN_PATH=`swift build --show-bin-path`
XCTEST_PATH=`find ${BIN_PATH} -name '*.xctest'`

COV_BIN=$XCTEST_PATH
if [[ "$OSTYPE" == "darwin"* ]]; then
	f=`basename $XCTEST_PATH .xctest`
	COV_BIN=$COV_BIN/Contents/MacOS/$f
fi

cd $PACKAGE_PATH

llvm-cov report $COV_BIN \
	-instr-profile=.build/debug/codecov/default.profdata \
	-ignore-filename-regex=".build|Tests"

swift-cov-show

ファイルを渡してあげることでそのファイルのみを表示します。

#!/bin/env sh

PACKAGE_PATH=`find-root-path Package.swift`

if [[ -z $PACKAGE_PATH ]]; then
	echo "$(pwd) is not swift package"
	exit 1
fi

BIN_PATH=`swift build --show-bin-path`
XCTEST_PATH=`find $BIN_PATH -name '*.xctest'`

COV_BIN=$XCTEST_PATH
if [[ "$OSTYPE" == "darwin"* ]]; then
	f=`basename $XCTEST_PATH .xctest`
	COV_BIN=$COV_BIN/Contents/MacOS/$f
fi

llvm-cov show $COV_BIN \h
	-instr-profile=$PACKAGE_PATH/.build/debug/codecov/default.profdata \
	-use-color \
	$@

find-root-path

#!/usr/bin/env sh

if [ $# != 1 -o $1 == "-h" -o $1 == "--help" ]; then
	echo "USAGE: find-root-path FILENAME"
	exit 1
fi

while [[ `pwd` != "/" ]]; do
	ls -A | grep -w $1 > /dev/null && pwd && exit 0
	cd ..
done

exit 1

swift-cov-show-use-colorを使っているのでパイプに渡しづらいことに注意してください。lessで見るときはless -RでANSIコードを解釈してくれます。swift-cov-report-use-colorは使っていませんが、標準出力とパイプとで出力を分けてくれます。

シェルスクリプトは初心者もいいところなので、特にfind-root-pathとかもっといい書き方があればご教示していただくと幸いです。

参考

https://theswiftdev.com/code-coverage-for-swift-package-manager-based-apps/
http://www.koganemaru.co.jp/cgi-bin/mroff.cgi?sect=1&cmd=&lc=1&subdir=man&dir=jpman-11.3.2%2Fman&subdir=man&man=llvm-cov

Discussion