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.Simplethis 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 = printlocal string = stringlocal setmetatable = setmetatablelocal debug = debugmodule("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 })endfunction TestCase:ok(test, name)if test thenprint(string.format('ok - %s.', name)) self.count_success = self.count_success + 1elseprint(string.format('not ok - %s.', name))print(debug.traceback(string.format('#failed in %s.', name))) self.count_fail = self.count_fail + 1endendfunction TestCase:report()local s = ''if self.tests == self.count_success thenif self.count_success > 1 then s = 's'endprint(string.format('Looks like you succeeded %s test%s.', self.count_success, s))elseif self.count_fail > 1 then s = 's'endprint(string.format('Looks like you failed %s test%s of %s.', self.count_fail, s, self.tests))endend-- vim: set ts=4 sw=4 sts=4 expandtab :
まあ、実用のためには、いろいろ機能が足りないですが、今後自分でも使っていくようなら、改善していこうと思います。