tl;dr
inokara.hateblo.jp
これの続きです。
当初は...
WordPress のプラグインバージョンをパースする処理を以下のように書いていました。
echo ${plugin_name} | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+)?" | sed 's/.//'
これは、プラグインのバージョン番号が以下のような状態を想定した処理でした。
- plugin-name.1.2.3.zip
- plugin-name.12345678.zip
- plugin-name-7.1.2.3.zip
実際に実行すると、以下のように、意図した通りにバージョン番号 (1.2.3
とか 12345678
等) が取得出来ます。
$ echo plugin-name.1.2.3.zip | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+)?" | sed 's/.//'
1.2.3
$ echo plugin-name.12345678.zip | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+)?" | sed 's/.//'
12345678
$ echo plugin-name-7.1.2.3.zip | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+)?" | sed 's/.//'
1.2.3
とーころが...
新手が登場しました。
これを従来のパース処理で処理しようとすると...
$ echo plugin-name.1.2.3.4.zip | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+)?" | sed 's/.//'
1.2.3
冒頭の 3 桁のみがパースされる状態となりました...
改修、そして shellspec
正規表現検定 8 級なので、とりあえず試行錯誤。試行錯誤の結果、以下のように書くことで、なんとか意図したような結果を得ることが出来ました。
$ echo ${plugin_name} | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+|\.[0-9]+\.[0-9]+)?" | sed 's/.//'
先程の 4 桁バージョン番号を処理してみます。
$ echo plugin-name.1.2.3.4.zip | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+|\.[0-9]+\.[0-9]+)?" | sed 's/.//'
1.2.3.4
$ echo plugin-name-100.1.2.3.4.zip | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+|\.[0-9]+\.[0-9]+)?" | sed 's/.//'
1.2.3.4
意図した通りに解析されていることを確認しました。
そして shellspec (1)
今後も同じような変異種が現れる可能性もあり、試行錯誤している間にデグレしてしまう可能性もあったので、この処理を関数化してユニットテストを書くようにしました。
そこで、テストフレームワークとして shellspec を選びました。
github.com
選んだ理由としては、特に強いこだわりがあったわけではありませんが、Rspec っぽく書けるという触れ込みだったので、お試し程度に使ってみようと思った次第です。
インストールの手順等は割愛しますが、今回は macOS に homebrew でインストールして利用しました。
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.7
BuildVersion: 19H114
$ brew tap shellspec/shellspec
$ brew install shellspec
以下のように実行して、shellspec を初期化します。
$ mkdir project
$ cd project
$ shellspec --init
project ディレクトリ直下に .shellspec
ファイルと spec
ディレクトリ、spec
ディレクトリ以下に spec_helper.sh
ファイルが作成されます。
そして shellspec (2)
以下のようにテスト対象の関数を用意しました。
$ cd project
$ vim lib/version-number-parse
function version_number_parse {
echo $1 | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+|\.[0-9]+\.[0-9]+)?" | sed 's/.//'
}
そして、テストは以下のように用意しました。
$ vim spec/version-number-parse_spec.sh
Describe "Check for version-number-parse script"
Include lib/version-number-parse
Describe "Call version_number_parse"
It "plugin-name.3.1.21.11.zip"
When call version_number_parse plugin-name.3.1.21.11.zip
The output should eq "3.1.21.11"
End
It "plugin-name.3.10.2.zip"
When call version_number_parse plugin-name.3.10.2.zip
The output should eq "3.10.2"
End
It "plugin-name.3.9.2.zip"
When call version_number_parse plugin-name.3.9.2.zip
The output should eq "3.9.2"
End
It "plugin-name.1.2.zip"
When call version_number_parse plugin-name.1.2.zip
The output should eq "1.2"
End
It "plugin-name-7.1.2.3.zip"
When call version_number_parse plugin-name-7.1.2.3.zip
The output should eq "1.2.3"
End
It "plugin-name.12345678.zip"
When call version_number_parse plugin-name.12345678.zip
The output should eq "12345678"
End
End
End
後は、以下のように実行します。
$ shellspec --format document -s bash
以下のように出力されました。
$ cd project
$ shellspec --format document -s bash
Running: /bin/bash [bash 3.2.57(1)-release]
Check for version-number-parse script
Call version_number_parse
plugin-name.3.1.21.11.zip
plugin-name.3.10.2.zip
plugin-name.3.9.2.zip
plugin-name.1.2.zip
plugin-name-7.1.2.3.zip
plugin-name.12345678.zip
Finished in 0.37 seconds (user 0.31 seconds, sys 0.07 seconds)
6 examples, 0 failures
Fail させてみると、以下のように出力されました。
$ shellspec --format document -s bash
Running: /bin/bash [bash 3.2.57(1)-release]
Check for version-number-parse script
Call version_number_parse
plugin-name.3.1.21.11.zip
plugin-name.3.10.2.zip
plugin-name.3.9.2.zip (FAILED - 1)
plugin-name.1.2.zip
plugin-name-7.1.2.3.zip
plugin-name.12345678.zip
Examples:
1) Check for version-number-parse script Call version_number_parse plugin-name.3.9.2.zip
When call version_number_parse plugin-name.3.9.2.zip
1.1) The output should eq 3.9.1
expected: "3.9.1"
got: "3.9.2"
Finished in 0.33 seconds (user 0.31 seconds, sys 0.07 seconds)
6 examples, 1 failure
Failure examples / Errors: (Listed here affect your suite's status)
shellspec spec/ver-check_spec.sh:14 # 1) Check for ver-check script Call get_current_version plugin-name.3.9.2.zip FAILED
いい感じ!shellspec
テスト結果の出力
以下のように --format
オプションで指定可能です。
$ shellspec -s bash
Running: /bin/bash [bash 3.2.57(1)-release]
......
Finished in 0.32 seconds (user 0.31 seconds, sys 0.07 seconds)
6 examples, 0 failures
$ shellspec --format junit -s bash
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="6" time="0.32" errors="0" failures="0" name="ver-check">
<testsuite id="0" tests="6" errors="0" failures="0" skipped="0" name="spec/version-number-parse_spec.sh" hostname="oreno-mac" timestamp="2021-01-05T15:22:57">
<testcase time="0" classname="spec/version-number-parse_spec.sh" name="Check for version-number-parse script Call version_number_parse plugin-name.3.1.21.11.zip"></testcase>
<testcase time="0" classname="spec/version-number-parse_spec.sh" name="Check for version-number-parse script Call version_number_parse plugin-name.3.10.2.zip"></testcase>
<testcase time="0" classname="spec/version-number-parse_spec.sh" name="Check for version-number-parse script Call version_number_parse plugin-name.3.9.2.zip"></testcase>
<testcase time="0" classname="spec/version-number-parse_spec.sh" name="Check for version-number-parse script Call version_number_parse plugin-name.1.2.zip"></testcase>
<testcase time="0" classname="spec/version-number-parse_spec.sh" name="Check for version-number-parse script Call version_number_parse plugin-name-7.1.2.3.zip"></testcase>
<testcase time="0" classname="spec/version-number-parse_spec.sh" name="Check for version-number-parse script Call version_number_parse plugin-name.12345678.zip"></testcase>
</testsuite>
</testsuites>
テストを実行するシェルを指定する
デフォルトでは、/bin/sh
が使われるとのことですが、--shell
又は -s
オプションでシェルを指定することが出来ます。
$ shellspec -s bash
上記の例では、その名の通り、bash を利用することになります。
CircleCI のオフィシャル Docker イメージである、cimg/python:3.6 上で shellspec を利用しようとした際に、このイメージのデフォルトシェルは /bin/sh
で、その実体は dash となっており、function
がサポートしていないことでエラーとなりテストが実行されずに焦りました。
circleci@0c366a26ccfd:~/project$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Apr 3 2020 /bin/sh -> dash
circleci@0c366a26ccfd:/project$ cat lib/version-number-parse
function version_number_parse {
echo $1 | grep -o -E "(\.[0-9]+|\.[0-9]+\.){1}[0-9]+(\.[0-9]+|\.[0-9]+\.[0-9]+)?" | sed 's/.//'
}
circleci@0c366a26ccfd:/project$ shellspec
/bin/sh: 1: lib/version-number-parse: function: not found
Unexpected output to stderr occurred at line 1-2 in 'spec/version-number-parse_spec.sh'
Running: /bin/sh [sh]
Finished in 0.16 seconds (user 0.04 seconds, sys 0.01 seconds)
0 examples, 0 failures, aborted by an unexpected error
Aborted with status code [executor: 127] [reporter: 1] [error handler: 102]
Fatal error occurred, terminated with exit status 102.
circleci@0c366a26ccfd:/project$ shellspec --shell bash
Running: /bin/bash [bash 4.4.20(1)-release]
......
Finished in 0.27 seconds (user 0.23 seconds, sys 0.06 seconds)
6 examples, 0 failures
上記のように --shell bash
を追加して実行することで、テストが正常に実行されました。
以上
WordPress のプラグインバージョンの付け方に翻弄されてしまいましたが、シェルスクリプトでもテストを書くと良いということと、shellspec に出会うことが出来て良かったというお話でした。
参考
github.com
qiita.com
qiita.com