Lua勉強日記(11) Luaのモジュールの仕組み

ある程度の大きさのシステムを作る場合、パッケージやモジュールの仕組みが無いと、考えることが多くなりすぎて大変です。

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 :

まあ、実用のためには、いろいろ機能が足りないですが、今後自分でも使っていくようなら、改善していこうと思います。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください