4.テストの定石−ログ文字列(Log String)−

これからいくつかテストの定石を紹介します。一番最初は、ログ文字列(Log String)です。

この定石は複雑な呼び出しシーケンスがあるときに、ちゃんと意図したとおりにメソッドが呼び出されたかどうか確認するためのものです。「論よりコード」とも言いますので、まず「1.座標の足し算」の最後で、initialize()、setup(),teardown()の順番を確認するために書いたコードをこの定石を使って書き直してみましょう。

---PointTest.rb----------------------
class PointTest < Test::Unit::TestCase
    def initialize(method)
        super
        @log = "initialize() "
    end
    
    def setup()
        @log.concat("setup() ")
        @point = Point.new(3, 4)
    end
    
    def teardown()
        @log.concat("teardown() ")
    end
    
    def testGetXY()
        assert_equal("initialize() setup() ", @log)
        assert_equal(3, @point.getX())
        assert_equal(4, @point.getY())
    end
    
    def testPlus()
        assert_equal("initialize() setup() ", @log)
        assert_equal(Point.new(5, 5), @point.plus(Point.new(2, 1)))
    end
    
    def testMinus()
        assert_equal("initialize() setup() ", @log)
        assert_equal(Point.new(1, 3), @point.minus(Point.new(2, 1)))
    end
    
    def testPoduct()
        assert_equal("initialize() setup() ", @log)
        assert_equal(Point.new(6, 8), @point.product(2))
    end
    
    def testDevide()
        assert_equal("initialize() setup() ", @log)
        assert_equal(Point.new(1, 2), @point.devide(2))
    end
end
--------------------------------

initialize()でメンバー変数@logを"initialize() "で初期化し、setup()で@logに"setup() "を付け加えています。したがって、意図した順番でinitialize()とsetup()が呼ばれれば、各テストメソッドを実行するときには@logは"initialize() setup() "になっているはずです。

テストを動かします。

Green bar
>$ ruby PointTest.rb
Loaded suite PointTest
Started
.....
Finished in 0.0 seconds.

5 tests, 11 assertions, 0 failures, 0 errors

意図した順番でinitialize()とsetup()が呼ばれたことが、出力結果を注意してみなくてもわかります。

たったこれだけのことですが、複数のオブジェクトが複雑に相互作用しているときには重宝するテスト方法です。

上記の例では、PointTestのなかでTestCaseの使われ方テストしていましたが、ちゃんとTestCaseの使われ方のテストを分離して書いて見ましょう。

---TestCaseTest.rb----------------------
require 'test/unit'
require 'test/unit/ui/console/testrunner'


class TestCaseTest < Test::Unit::TestCase
    def initialize(method)
        super
        @log = "initialize() "
    end
    
    def setup()
        @log.concat("setup() ")
    end
    
    def teardown()
        @log.concat("teardown() ")
    end
    
    def testA()
        @log.concat("testA() ")
    end
    
    def getLog()
        return @log
    end
end

class TestCaseTestTest < Test::Unit::TestCase
    def setup()
        #TestCaseTestのtestAをテストするインスタンスを作ります。
        @test = TestCaseTest.new("testA")
    end
    
    def testTestCase()
        #テストをrunさせます。
        Test::Unit::UI::Console::TestRunner.run(@test)

        #ログを確認します。
        assert_equal("initialize() setup() testA() teardown() ", @test.getLog())
    end
end
--------------------------------

TestCaseTestでlogを書くようにして、TestCaseTestTestからTestCaseTestのインスタンスを作ってrunさせ、TestCaseTestのログを確かめています。これならちゃんとteardownが呼ばれたところまで確かめられますね。このようにテスト対象のオブジェクトにログを持たせて、テストからテスト対象のログをチェックするのが普通のやり方です。


[上] [前]