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.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 :

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

コメントする

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


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

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