ablog

不器用で落着きのない技術者のメモ

シェルスクリプトのユニットテストフレームワーク "shUnit2" を使ってみた

ないだろうと思いながらぐぐってみたら、

shUnit2 is a xUnit unit test framework for Bourne based shell scripts, and it is designed to work in a similar manner to JUnit, PyUnit, etc. If you have ever had the desire to write a unit test for a shell script, shUnit2 can do the job.

Google Code Archive - Long-term storage for Google Code Project Hosting.

あるじゃないか!

とりあえず、動かしてみよ。

shunit2 をダウンロードして解凍して、

$ mkdir -p ~/Documents/src/shunit2
$ perl -MLWP::Simple -e 'getstore("http://shunit2.googlecode.com/files/shunit2-2.1.5.tgz","shunit2-2.1.5.tgz")';
$ tar xvfz shunit2-2.1.5.tgz 

サンプルを実行してみると、

$ cd shunit2-2.1.5/examples
$ ./equality_test.sh 
testEquality

Ran 1 test.

OK

おお、なんか動いたぞw
もう一つサンプルを動かしてみる。

$ ./party_test.sh 
testEquality
testPartyLikeItIs1999
ASSERT:It's not 1999 :-( expected:<1999> but was:<2010>

Ran 2 tests.

FAILED (failures=1)

実行したテストコードは以下の通り。

$ cat equality_test.sh 
#! /bin/sh
# file: examples/equality_test.sh

testEquality()
{
  assertEquals 1 1
}

# load shunit2
. ../src/shell/shunit2
#! /bin/sh
# file: examples/party_test.sh

testEquality()
{
  assertEquals 1 1
}

testPartyLikeItIs1999()
{
  year=`date '+%Y'`
  assertEquals "It's not 1999 :-(" \
      '1999' "${year}"
}

# load shunit2
. ../src/shell/shunit2


ドキュメントを読んで、本格的に使ってみよ。

Hopefully, this is enough to get you started with unit testing. If you want a ton more examples, take a look at the tests provided with log4sh or shFlags. Both provide excellent examples of more advanced usage. shUnit2 was after all written to help with the unit testing problems that log4sh had.

http://shunit2.googlecode.com/svn/trunk/source/2.1/doc/shunit2.html

もっと例を見たけりゃ、log4sh や shFlags のテストコードが山ほどあるよってか。


log4sh のテストコードをちょっと見てみよう。

$ cd ~/Documents/src/log4sh
$ perl -MLWP::Simple -e 'getstore("http://downloads.sourceforge.net/log4sh/log4sh-1.4.2.tgz","log4sh-1.4.2.tgz")';
$ tar xfvz log4sh-1.4.2.tgz 
$ cd ~/log4sh-1.4.2/src/test
$ ls -l
total 264
-rw-r--r--  1 yohei  staff   1097  8 11  2006 log4sh.properties
-rw-r--r--  1 yohei  staff    501  1  1  2007 priorityMatrix.data
-rwxr-xr-x  1 yohei  staff   2231  1  5  2007 run-test-suite
-rw-r--r--  1 yohei  staff   6687  8 15  2006 test-common
-rw-r--r--  1 yohei  staff   1862  1  4  2007 test-functions.inc
-rwxr-xr-x  1 yohei  staff   1373  3 25  2006 test-prop-config
-rwxr-xr-x  1 yohei  staff   2562  9 17  2006 test-runtime-config
-rwxr-xr-x  1 yohei  staff   1209  5 23  2007 testAsciiCharset
-rw-r--r--  1 yohei  staff    308  8 19  2006 testAsciiCharset.data
-rw-r--r--  1 yohei  staff    250  9  8  2006 testAsciiCharset.log4sh
-rwxr-xr-x  1 yohei  staff   3542  5 23  2007 testCustomMDCPatterns
-rwxr-xr-x  1 yohei  staff   4910  5 23  2007 testFileAppender
-rw-r--r--  1 yohei  staff    293  1  4  2007 testFileAppender-accessors.log4sh
-rw-r--r--  1 yohei  staff    191  9  8  2006 testFileAppender-mySTDERR.log4sh
-rw-r--r--  1 yohei  staff    246  9  8  2006 testFileAppender-mySimple.log4sh
-rwxr-xr-x  1 yohei  staff   1819  6  1  2007 testLog4jCompatibility
-rwxr-xr-x  1 yohei  staff   1878  5 23  2007 testMultipleAppenders
-rwxr-xr-x  1 yohei  staff   7381  5 23  2007 testPatternLayout
-rwxr-xr-x  1 yohei  staff   2348  5 23  2007 testPriority
-rwxr-xr-x  1 yohei  staff   1963  6  1  2007 testPropertyConfig
-rwxr-xr-x  1 yohei  staff  13815  5 23  2007 testRollingFileAppender
-rw-r--r--  1 yohei  staff    486 12 28  2006 testRollingFileAppender.log4sh
-rwxr-xr-x  1 yohei  staff   3663  5 23  2007 testSMTPAppender
-rw-r--r--  1 yohei  staff    428  1  5  2007 testSMTPAppender.log4sh
-rwxr-xr-x  1 yohei  staff   7979  6  3  2007 testSyslogAppender
-rw-r--r--  1 yohei  staff    211  1  4  2007 testSyslogAppender.data
$ egrep '^test[A-Z][a-zA-Z0-9]+\(\)' *
testAsciiCharset:testAsciiCharset()
testCustomMDCPatterns:testCustomDateMDC()
testCustomMDCPatterns:testCustomTimeMDC()
testCustomMDCPatterns:testCustomUserHostMDC()
testLog4jCompatibility:testAppenders()
testLog4jCompatibility:testLayouts()
testMultipleAppenders:testTwoSimilarFileAppenders()
testPatternLayout:testCategoryPattern()
testPatternLayout:testDatePattern()
testPatternLayout:testFileNamePattern()
testPatternLayout:testLineNumberPattern()
testPatternLayout:testLineSeparatorPattern()
testPatternLayout:testMessagePattern()
testPatternLayout:testPriorityPattern()
testPatternLayout:testRunningTimePattern()
testPatternLayout:testThreadNamePattern()
testPatternLayout:testNDCPattern()
testPatternLayout:testMDCPattern()
testPatternLayout:testPercentPattern()
testPatternLayout:testDefaultPattern()
testPriority:testPriorityMatrix()
testPriority:testInvalidPriority()
testPropertyConfig:testAppenders()
testPropertyConfig:testLayouts()
testPropertyConfig:testLayoutTypes()
testRollingFileAppender:testEmptyFile()
testRollingFileAppender:testOneByteUnderSize()
testRollingFileAppender:testExactlyRightSize()
testRollingFileAppender:testOneByteOverSize()
testRollingFileAppender:testOrderOfMagnitudeLarger()
testRollingFileAppender:testMaxBackupIndexOf2()
testRollingFileAppender:testMaxBackupIndexOf1()
testRollingFileAppender:testMaxBackupIndexOf0()
testRollingFileAppender:testMaxFileSizeGetterSetter()
testSMTPAppender:testSubjectGetterSetter()
testSMTPAppender:testToGetterSetter()
testSMTPAppender:testAppenderSetupFromConfig()
testSyslogAppender:testFacilityGetterSetter()
testSyslogAppender:testHostGetterSetter()
testSyslogAppender:testPriorityMatrix()
testSyslogAppender:testRemoteLogging()

log4sh のテストを走らせてみよ。
準備して、

$ cp -p ~/Documents/src/shunit2/shunit2-2.1.5/src/shell/* ~/Documents/src/log4sh/log4sh-1.4.2/src/test/
$ cp -p ~/Documents/src/log4sh/log4sh-1.4.2/src/shell/log4sh ~/Documents/src/log4sh/log4sh-1.4.2/src/test/
$ cd ~/Documents/src/log4sh/log4sh-1.4.2/src/test/ 

Go!

$ ./run-test-suite 
#------------------------------------------------------------------------------
# System data
#

# test run info
shells="/bin/sh /bin/bash /bin/dash /bin/ksh /bin/pdksh"
tests="testAsciiCharset testCustomMDCPatterns testFileAppender testLog4jCompatibility testMultipleAppenders testPatternLayout testPriority testPropertyConfig testRollingFileAppender testSMTPAppender testSyslogAppender"

# system info
$ date
201022日 火曜日 081108秒 JST
$ uname -mprsv
Darwin 9.6.0 Darwin Kernel Version 9.6.0: Mon Nov 24 17:37:00 PST 2008; root:xnu-1228.9.59~1/RELEASE_I386 i386 i386


#------------------------------------------------------------------------------
# Running the test suite with /bin/sh
#

--- Executing the 'AsciiCharset' test suite ---
testAsciiCharset
ASSERT:'PQRSTUVWXYZ[\]^_' != 'PQRSTUVWXYZ[]^_' expected:<PQRSTUVWXYZ[\]^_> but was:<PQRSTUVWXYZ[]^_>

Ran 1 test.

FAILED (failures=1)

--- Executing the 'CustomMDCPatterns' test suite ---
testCustomDateMDC
testCustomTimeMDC
testCustomUserHostMDC

Ran 3 tests.

OK

--- Executing the 'FileAppender' test suite ---
testSTDERR_runtime
testSTDERR_config
testSimple_runtime
testSimple_config
testAccessors_getFilename
testAccessors_setgetFilename

Ran 6 tests.

OK

--- Executing the 'Log4jCompatibility' test suite ---
testAppenders
testLayouts

Ran 2 tests.

OK

--- Executing the 'MultipleAppenders' test suite ---
testTwoSimilarFileAppenders

Ran 1 test.

OK

--- Executing the 'PatternLayout' test suite ---
testCategoryPattern
testDatePattern
testFileNamePattern
testLineNumberPattern
testLineSeparatorPattern
testMessagePattern
testPriorityPattern
testRunningTimePattern
testThreadNamePattern
testNDCPattern
testMDCPattern
testPercentPattern

Ran 12 tests.

OK

--- Executing the 'Priority' test suite ---
testPriorityMatrix
testInvalidPriority
log4sh:ERROR invalid logging level requested (INVALID)

Ran 2 tests.

OK

--- Executing the 'PropertyConfig' test suite ---
testAppenders
- expecting one error
log4sh:ERROR appender type (InvalidAppender) unrecognized
testLayouts
- expecting one error
log4sh:ERROR unknown layout: InvalidLayout
testLayoutTypes
- expecting one error
log4sh:ERROR layout value/method (InvalidType) unrecognized

Ran 3 tests.

OK

--- Executing the 'RollingFileAppender' test suite ---
testEmptyFile_runtime
testOneByteUnderSize_runtime
testExactlyRightSize_runtime
testOneByteOverSize_runtime
testOrderOfMagnitudeLarger_runtime
testEmptyFile_config
testOneByteUnderSize_config
testExactlyRightSize_config
testOneByteOverSize_config
testOrderOfMagnitudeLarger_config
testMaxBackupIndexOf2
testMaxBackupIndexOf1
testMaxBackupIndexOf0
testMaxFileSizeGetterSetter
- expecting one warning
log4sh:WARN missing file size unit; assuming bytes
- expecting one error
log4sh:ERROR unrecognized file size unit 'foo'

Ran 14 tests.

OK

--- Executing the 'SMTPAppender' test suite ---
testSubjectGetterSetter
testToGetterSetter
testAppenderSetupFromConfig

Ran 3 tests.

OK

--- Executing the 'SyslogAppender' test suite ---
testFacilityGetterSetter
log4sh:ERROR [invalid] is an unknown syslog facility. Defaulting to [user].
ASSERT:the returned syslog facility (user) matches the invalid one set (invalid) expected not same
testHostGetterSetter
log4sh:WARN the nc (netcat) command alternative is required for remote syslog logging. see log4sh_setAlternative().
testPriorityMatrix
  testing appender priority 'TRACE'
  testing appender priority 'DEBUG'
  testing appender priority 'INFO'
  testing appender priority 'WARN'
  testing appender priority 'ERROR'
  testing appender priority 'FATAL'
  testing appender priority 'OFF'
testRemoteLogging
log4sh:ERROR log4sh_setAlternative(): nc: command not found
log4sh:WARN the nc (netcat) command alternative is required for remote syslog logging. see log4sh_setAlternative().

Ran 4 tests.

FAILED (failures=1,skipped=43)


#------------------------------------------------------------------------------
# Running the test suite with /bin/bash
#

GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.

--- Executing the 'AsciiCharset' test suite ---
testAsciiCharset

Ran 1 test.

OK

--- Executing the 'CustomMDCPatterns' test suite ---
testCustomDateMDC
testCustomTimeMDC
testCustomUserHostMDC

Ran 3 tests.

OK

--- Executing the 'FileAppender' test suite ---
testSTDERR_runtime
testSTDERR_config
testSimple_runtime
testSimple_config
testAccessors_getFilename
testAccessors_setgetFilename

Ran 6 tests.

OK

--- Executing the 'Log4jCompatibility' test suite ---
testAppenders
testLayouts

Ran 2 tests.

OK

--- Executing the 'MultipleAppenders' test suite ---
testTwoSimilarFileAppenders

Ran 1 test.

OK

--- Executing the 'PatternLayout' test suite ---
testCategoryPattern
testDatePattern
testFileNamePattern
testLineNumberPattern
testLineSeparatorPattern
testMessagePattern
testPriorityPattern
testRunningTimePattern
testThreadNamePattern
testNDCPattern
testMDCPattern
testPercentPattern

Ran 12 tests.

OK

--- Executing the 'Priority' test suite ---
testPriorityMatrix
testInvalidPriority
log4sh:ERROR invalid logging level requested (INVALID)

Ran 2 tests.

OK

--- Executing the 'PropertyConfig' test suite ---
testAppenders
- expecting one error
log4sh:ERROR appender type (InvalidAppender) unrecognized
testLayouts
- expecting one error
log4sh:ERROR unknown layout: InvalidLayout
testLayoutTypes
- expecting one error
log4sh:ERROR layout value/method (InvalidType) unrecognized

Ran 3 tests.

OK

--- Executing the 'RollingFileAppender' test suite ---
testEmptyFile_runtime
testOneByteUnderSize_runtime
testExactlyRightSize_runtime
testOneByteOverSize_runtime
testOrderOfMagnitudeLarger_runtime
testEmptyFile_config
testOneByteUnderSize_config
testExactlyRightSize_config
testOneByteOverSize_config
testOrderOfMagnitudeLarger_config
testMaxBackupIndexOf2
testMaxBackupIndexOf1
testMaxBackupIndexOf0
testMaxFileSizeGetterSetter
- expecting one warning
log4sh:WARN missing file size unit; assuming bytes
- expecting one error
log4sh:ERROR unrecognized file size unit 'foo'

Ran 14 tests.

OK

--- Executing the 'SMTPAppender' test suite ---
testSubjectGetterSetter
testToGetterSetter
testAppenderSetupFromConfig

Ran 3 tests.

OK

--- Executing the 'SyslogAppender' test suite ---
testFacilityGetterSetter
log4sh:ERROR [invalid] is an unknown syslog facility. Defaulting to [user].
ASSERT:the returned syslog facility (user) matches the invalid one set (invalid) expected not same
testHostGetterSetter
log4sh:WARN the nc (netcat) command alternative is required for remote syslog logging. see log4sh_setAlternative().
testPriorityMatrix
  testing appender priority 'TRACE'
  testing appender priority 'DEBUG'
  testing appender priority 'INFO'
  testing appender priority 'WARN'
  testing appender priority 'ERROR'
  testing appender priority 'FATAL'
  testing appender priority 'OFF'
testRemoteLogging
log4sh:ERROR log4sh_setAlternative(): nc: command not found
log4sh:WARN the nc (netcat) command alternative is required for remote syslog logging. see log4sh_setAlternative().

Ran 4 tests.

FAILED (failures=1,skipped=43)

run-test-suite:WARN unable to run tests with the /bin/dash shell


#------------------------------------------------------------------------------
# Running the test suite with /bin/ksh
#

  version         sh (AT&T Research) 1993-12-28 s+

--- Executing the 'AsciiCharset' test suite ---
testAsciiCharset

Ran 1 test.

OK

--- Executing the 'CustomMDCPatterns' test suite ---
testCustomDateMDC
testCustomTimeMDC
testCustomUserHostMDC

Ran 3 tests.

OK

--- Executing the 'FileAppender' test suite ---
testSTDERR_runtime
testSTDERR_config
testSimple_runtime
testSimple_config
testAccessors_getFilename
testAccessors_setgetFilename

Ran 6 tests.

OK

--- Executing the 'Log4jCompatibility' test suite ---
testAppenders
testLayouts

Ran 2 tests.

OK

--- Executing the 'MultipleAppenders' test suite ---
testTwoSimilarFileAppenders

Ran 1 test.

OK

--- Executing the 'PatternLayout' test suite ---
testCategoryPattern
testDatePattern
testFileNamePattern
testLineNumberPattern
testLineSeparatorPattern
testMessagePattern
testPriorityPattern
testRunningTimePattern
testThreadNamePattern
testNDCPattern
testMDCPattern
testPercentPattern

Ran 12 tests.

OK

--- Executing the 'Priority' test suite ---
testPriorityMatrix
testInvalidPriority
log4sh:ERROR invalid logging level requested (INVALID)

Ran 2 tests.

OK

--- Executing the 'PropertyConfig' test suite ---
testAppenders
- expecting one error
log4sh:ERROR appender type (InvalidAppender) unrecognized
testLayouts
- expecting one error
log4sh:ERROR unknown layout: InvalidLayout
testLayoutTypes
- expecting one error
log4sh:ERROR layout value/method (InvalidType) unrecognized

Ran 3 tests.

OK

--- Executing the 'RollingFileAppender' test suite ---
testEmptyFile_runtime
testOneByteUnderSize_runtime
testExactlyRightSize_runtime
testOneByteOverSize_runtime
testOrderOfMagnitudeLarger_runtime
testEmptyFile_config
testOneByteUnderSize_config
testExactlyRightSize_config
testOneByteOverSize_config
testOrderOfMagnitudeLarger_config
testMaxBackupIndexOf2
testMaxBackupIndexOf1
testMaxBackupIndexOf0
testMaxFileSizeGetterSetter
- expecting one warning
log4sh:WARN missing file size unit; assuming bytes
- expecting one error
log4sh:ERROR unrecognized file size unit 'foo'

Ran 14 tests.

OK

--- Executing the 'SMTPAppender' test suite ---
testSubjectGetterSetter
testToGetterSetter
testAppenderSetupFromConfig

Ran 3 tests.

OK

--- Executing the 'SyslogAppender' test suite ---
testFacilityGetterSetter
log4sh:ERROR [invalid] is an unknown syslog facility. Defaulting to [user].
ASSERT:the returned syslog facility (user) matches the invalid one set (invalid) expected not same
testHostGetterSetter
log4sh:WARN the nc (netcat) command alternative is required for remote syslog logging. see log4sh_setAlternative().
testPriorityMatrix
  testing appender priority 'TRACE'
  testing appender priority 'DEBUG'
  testing appender priority 'INFO'
  testing appender priority 'WARN'
  testing appender priority 'ERROR'
  testing appender priority 'FATAL'
  testing appender priority 'OFF'
testRemoteLogging
log4sh:ERROR log4sh_setAlternative(): nc: command not found
log4sh:WARN the nc (netcat) command alternative is required for remote syslog logging. see log4sh_setAlternative().

Ran 4 tests.

FAILED (failures=1,skipped=43)

run-test-suite:WARN unable to run tests with the /bin/pdksh shell

お、そこそこ走ってる。なんか雰囲気がつかめてきた。