CircleCIでshUnit2のテストを実施する

  • 0
    Like
  • 0
    Comment
    More than 1 year has passed since last update.

    先日、「shUnit2を使おう」という以下のLTをしてきました。
    http://www.slideshare.net/cottondesu/shell-02-shunit2

    shUnit2を使ってシェルのテストするまでLTをしましたが、
    本当はこのLTには続きあります。
    動作確認する時間、スライドを作成する時間がなかったので実現
    できなかったのですが、GithubとCircleCIが連携し
    CircleCIでshUnit2のシェルテストを行うことです。

    目的

    Githubにpushし、CircleCIでshUnit2のテストを実施する

    環境

    • Mac
    • shUnit2
    • Github
    • CircleCI

    shUnit2のインストール

    以下のURLを開く
    https://code.google.com/archive/p/shunit2/

    Downloadsからshunit2-2.1.6.tgzをダウンロードします。
    ターミナルから以下のコマンドを実行しフォルダを作成、
    ダウンロードしたtgzファイルを展開します。

    $ mkdir ~/.shunit2
    $ tar zxf shunit2-2.1.6.tgz -C ~/.shunit2
    

    以下のように環境変数(bash)を設定します。

    $ echo 'export SHUNIT2_HOME=$HOME/.shunit2/shunit2-2.1.6' >> ~/.bash_profile
    $ . ~/.bash_profile
    

    sampleのテストコードは.shUnit2のexamplesディレクトリに
    格納されているのでそちらでテストコードの書き方を確認ください。

    bashスクリプトのプロジェクト作成

    テスト対象のシェルスクリプトとテストコードが必要になります。
    ここではテストコードの書き方は省きます。
    私の場合、シェルスクリプトがGithubにおいてあるのでこちらを使います。

    https://github.com/cottondesu/shell_create_kzrb_meetup

    シェルスクリプトのテスト対象ファンクション部分

    create_kzrb_meetup.sh
    #モード選択
    select_mode() {
      if [[ "$1" =~ ^[1-2] ]]; then
        return 0
      else
        return 1
      fi
    }
    
    #meetup番号入力  
    input_meetupnum(){
      if [[ "$1" =~ ^[0-9]+$ ]]; then
        return 0
      else
        return 1
      fi  
    }
    
    #フォルダ存在チェック
    is_filefolder(){
      if [ ! -e "$1" ]; then
        return 1
      else
        return 0
      fi  
    }
    

    テストコード

    test/function_test.sh
    #!/bin/bash
    
    # shellcheck source=./../../shell_create_kzrb_meetup/create_kzrb_meetup.sh
    . "$(dirname "${BASH_SOURCE:-$0}")/../../shell_create_kzrb_meetup/create_kzrb_meetup.sh"
    
    testSelectMode1(){
        select_mode 1
        assertEquals 0 $?
    }
    
    testSelectMode2(){
        select_mode 2
        assertEquals 0 $?
    }
    
    testSelectModeNg(){
        select_mode 3
        assertEquals 1 $?
    }
    
    testInputMeetupNum1(){
        input_meetupnum 1
        assertEquals 0 $?
    }
    
    testInputMeetupNum40(){
        input_meetupnum 40
        assertEquals 0 $?
    }
    
    testInputMeetupNumNg(){
        input_meetupnum a
        assertEquals 1 $?
    }
    
    testIsFile(){
        is_filefolder "$0"
        assertEquals 0 $?
    }
    
    testIsFileNg(){
        is_filefolder "index.md"
        assertEquals 1 $?
    }
    
    testIsFolder(){
        is_filefolder ../test
        assertEquals 0 $?
    }
    
    testIsFolderNg(){
        is_filefolder test
        assertEquals 1 $?
    }
    
    # shellcheck source=$HOME/.shunit2/shunit2-2.1.6/src/shunit2
    . "$SHUNIT2_HOME/src/shunit2"
    

    因みに上記のfunction_test.shをshellcheckするとnoteが2件でます。
    shellcheck -xで実行すると57行目の1件のみnoteで出ます。
    $HOMEを実際のパスに置き換えるとnoteが消えます。

    Githubにpush

    私の場合は既にGithubにシェルスクリプトが格納されているので
    テストコードを追加してpushします。

    $ git add test/function_test.sh
    $ git commit -m "テストコードを追加"
    $ git push origin master
    

    CircleCIの設定

    CircleCI
    https://circleci.com/

    1. CircleCIにgithubのアカウントでログインする
    2. 左側のメニューにある[ADD PROJECT]を選択する
    3. pushしたリポジトリの「BuildProject」を選択する。

    3.を行うとすぐさまbuildが実施されますが、
    「NO TESTS」となります。testが実施されていませんからね。

    testが実施されるようにcircle.ymlを作成する

    circle.yml
    machine:
      environment:
        SHUNIT2_HOME: ${HOME}/.shunit2/shunit2-2.1.6
    
    dependencies:
      pre:
        - "[ ! -e ~/.shunit2 ] && wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/shunit2/shunit2-2.1.6.tgz && mkdir ~/.shunit2 && tar zxf shunit2-2.1.6.tgz -C ~/.shunit2 || echo 'ready'"
      cache_directories:
        - "~/.shunit2"
    
    test:
      override:
        - bash test/function_test.sh
    

    test:の所でpush時に実行されるテストコードを指定します。
    私の場合は、test/function_test.sh となります。

    作成したcircle.ymlをpushする

    $ git add circle.yml
    $ git commit -m "add circle yml"
    $ git push origin master
    

    pushすると、CircleCI上でshUnit2によるテストが実行されます。
    ここで成功したよドヤって言いたかったんですが、私のテストコードが
    悪かったせいでFAILEDになってしまいました。

    ローカル環境でのテスト実施はtestフォルダに移動して
    テストコードを実施していました。

    $ sh function_test.sh
    

    上の階層(shell_create_kzrb_meetup)に移動して
    テストコードを実施すると、CircleCIで実施した時と同じ
    FAILEDが再現できました。

    $ sh test/function_test.sh
    

    ファイル存在やフォルダ存在などパスを確認するテストコードを
    作成するときは実行するカレントフォルダを意識する必要があります。
    我が身を持って大変勉強になりました。

    以下のようにテストコードを直します。

    function_test.sh修正前
    testIsFolder(){
        is_filefolder ../test
        assertEquals 0 $?
    }
    
    testIsFolderNg(){
        is_filefolder test
        assertEquals 1 $?
    }
    
    function_test.sh
    testIsFolder(){
        is_filefolder test
        assertEquals 0 $?
    }
    
    testIsFolderNg(){
        is_filefolder exsample
        assertEquals 1 $?
    }
    

    として直してcommit、pushします。

    $ git add test/function_test.sh
    $ git commit -m "テストコードの修正"
    $ git push origin master 
    

    無事、単体テストが成功しました。
    本当は成功例のみを載せたほうが良いのかもしませんが
    失敗例含めて少しでも役に立てば有難いです。

    参考にした記事

    shUnit2とCircleCIでシェルスクリプトの単体テストをしてみた