Lua勉強日記(11) Luaのモジュールの仕組み
2008/06/12
ある程度の大きさのシステムを作る場合、パッケージやモジュールの仕組みが無いと、考えることが多くなりすぎて大変です。
Luaには、モジュールの仕組みがあるようです。cgiluaのソースを見ながら、使い方を手探りで試しているので、間違いがあったら、指摘していただけると嬉しいです。
- requireで、別のファイルを読み込むことができる。
- moduleで、モジュールのスコープを作れるらしい。module関数呼出しからfileの最後までが、モジュールのスコープになるようです。
- モジュールスコープは、全く別のnamespaceになるようで、何もしないとグローバル空間にある関数(printなど)も呼出せなくなる。
- module関数呼出し前に、local print = print のように、ファイルのスコープのレキシカル変数 print に、グローバルスコープのprint関数を格納してあげることで、モジュールのスコープ内でもprint関数を使用することができるようになる。
- (追記)モジュールスコープでも、普通にグローバルの関数などを呼出すには、module関数の第二引数にpackage.seeall を指定すればいいようです。module(“test.simple”, package.seeall)
モジュールの練習のために、Unit Test のモジュールを書いてみることにしました。
UIは簡単な方がいいので、perlのTest::Simpleを参考に、oop風にしてみました。
呼び出し方と実行結果
require("test.simple") t = test.simple.TestCase.new({tests = 3}) t:ok(1 == 1, "number test") t:ok("1" == "1", "string test") t:ok(true, "boolean test") t:report()
のようなファイルを実行すると、
$ lua5.1 testtest.lua ok - number test. ok - string test. ok - boolean test. Looks like you succeeded 3 tests.
と表示されるようにしました。
失敗するテストがある場合は、
not ok - number test. #failed in number test. stack traceback: .\test\simple.lua:38: in function 'ok' testtest.lua:4: in main chunk [C]: ? ok - string test. ok - boolean test. Looks like you failed 1 tests of 3.
と表示されるようにしてみました。
初めて作ったモジュールです。
test/simple.lua
--[[ test.Simple this is a simple test module like perl Test::Simple. require("test.simple") t = test.simple.new({tests = 3}) t:ok(1 == 1, "number test") t:ok("1" == "1", "string test") t:ok(true, "boolean test") t:report() ]]-- local print = print local string = string local setmetatable = setmetatable local debug = debug module("test.simple") -- TestCase Class TestCase = {} function TestCase.new(options) self = { tests = options.tests or 0, count_success = 0, count_fail = 0 } return setmetatable(self, { __index = TestCase }) end function TestCase:ok(test, name) if test then print(string.format('ok - %s.', name)) self.count_success = self.count_success + 1 else print(string.format('not ok - %s.', name)) print(debug.traceback(string.format('#failed in %s.', name))) self.count_fail = self.count_fail + 1 end end function TestCase:report() local s = '' if self.tests == self.count_success then if self.count_success > 1 then s = 's' end print(string.format('Looks like you succeeded %s test%s.', self.count_success, s)) else if self.count_fail > 1 then s = 's' end print(string.format('Looks like you failed %s test%s of %s.', self.count_fail, s, self.tests)) end end -- vim: set ts=4 sw=4 sts=4 expandtab :
まあ、実用のためには、いろいろ機能が足りないですが、今後自分でも使っていくようなら、改善していこうと思います。