lua-TestMore contains Lua 5.1 and 5.2 test suites announcement
luaunit
Itt egy egyszerű és könnyen érthető példa látható luaunit használatára.
-- Some super function to test
function my_super_function( arg1, arg2 ) return arg1 + arg2 end
-- Unit testing starts
local LuaUnit = require('luaunit')
TestMyStuff = {} --class
function TestMyStuff:testWithNumbers()
a = 1
b = 2
result = my_super_function( a, b )
assertEquals( type(result), 'number' )
assertEquals( result, 3 )
end
function TestMyStuff:testWithRealNumbers()
a = 1.1
b = 2.2
result = my_super_function( a, b )
assertEquals( type(result), 'number' )
-- I would like the result to be always rounded to an integer
-- but it won't work with my simple implementation
-- thus, the test will fail
assertEquals( result, 3 )
end
-- class TestMyStuff
LuaUnit:run()
Az előbbi kódot futtatva a következő lesz az eredmény
shell $ lua use_luaunit1.lua
>>>>>> TestMyStuff
>>> TestMyStuff:testWithNumbers
Ok
>>> TestMyStuff:testWithRealNumbers
use_luaunit1.lua:25: expected: 3.3, actual: 3
Failed
Success : 50% - 1 / 2
A teszt framework jelzi, melyik fáj, melyik sora okozott hibát, némi plusz információval.
A programkód növekdesével egyre több teszt estre is szükség lesz. A következő példa már valamivel bonyolultabb.
-- Some super function to test
function my_super_function( arg1, arg2 ) return arg1 + arg2 end
function my_bad_function( arg1, arg2 ) return arg1 - arg2 end
-- Unit testing starts
require('luaunit')
-- now, we perform all the tests on int in one test class
-- and the tests on float in another one
-- when your test grows, you will have many test classes
TestWithInt = {} --class
function TestWithInt:setUp()
-- this function is run before each test, so that multiple
-- tests can share initialisations
self.a = 1
self.b = 2
end
function TestWithInt:tearDown()
-- this function is executed after each test
-- here, we have nothing to do so we could have avoid
-- declaring it
end
function TestWithInt:testSuperFunction()
result = my_super_function( self.a, self.b )
assertEquals( type(result), 'number' )
assertEquals( result, 3 )
end
function TestWithInt:testBadFunction()
result = my_bad_function( self.a, self.b )
assertEquals( type(result), 'number' )
assertEquals( result, -1 )
end
function TestWithInt:testThatFails()
-- you can test anything with assertEquals
assertEquals( self.a, 1 )
assertEquals( type(self.a), 'number' )
-- will fail
assertEquals( 'hop', 'bof' )
end
-- class TestWithInt
TestWithFloat = {} --class
function TestWithFloat:setUp()
-- this function is run before each test, so that multiple
-- tests can share initialisations
self.a = 1.1
self.b = 2.1
end
function TestWithFloat:tearDown()
-- this function is executed after each test
-- here, we have nothing to do so we could have avoid
-- declaring it
end
function TestWithFloat:testSuperFunction()
result = my_super_function( self.a, self.b )
assertEquals( type(result), 'number' )
-- will fail
assertEquals( result, 3 )
end
function TestWithFloat:testBadFunction()
result = my_bad_function( self.a, self.b )
assertEquals( type(result), 'number' )
-- will work, but only by chance :-)
assertEquals( result, -1 )
end
-- class TestWithFloat
LuaUnit:run()
Futassuk a következővel
shell $ lua use_luaunit2.lua
>>>>>> TestWithFloat
>>> TestWithFloat:testSuperFunction
use_luaunit2.lua:66: expected: 3.2, actual: 3
Failed
>>> TestWithFloat:testBadFunction
Ok
>>>>>> TestWithInt
>>> TestWithInt:testSuperFunction
Ok
>>> TestWithInt:testBadFunction
Ok
>>> TestWithInt:testThatFails
use_luaunit2.lua:44: expected: 'hop', actual: 'bof'
Failed
Success : 60% - 3 / 5
Egyenként is futtathatóak a tesztek
shell $ lua use_luaunit2.lua TestWithInt:testSuperFunction
>>>>>> TestWithInt
>>> TestWithInt:testSuperFunction
Ok
Success : 100% - 1 / 1
shell $ lua use_luaunit2.lua TestWithFloat
>>>>>> TestWithFloat
>>> TestWithFloat:testSuperFunction
use_luaunit2.lua:66: expected: 3.2, actual: 3
Failed
>>> TestWithFloat:testBadFunction
Ok
Success : 50% - 1 / 2
Shake
Egyszrű és átlátható Lua "test engine", melyben a tesztek csak standard assert-eket és print call-okat használnak. Azok számára, akik xUnit stílusú frameworköt keresnek, ott az lunit és luaunit.
Sok Lua modul és alkalmazás használ egyszerű mintákat a belső tesztekhez. Általában rendelkeznek egy scripttel (gyakran test.lua), amely felhasználja a module API-t. Ez API hívások és assert() hívások segítségével értékeli ki az erdeményeket. Ezekben a modulokban szintén gyakori a print() használata. Ezzel kiirathatuunk információkat a teszt haladásáról, vagy hogy éppen mi áll tesztelés alatt. Bár a gyakorlatban ezt a fajta megközelítést igen sokan alkalmazzák, mégis túl nyers azok számára, akik több modult tesztelnének, illetve részletesebb eredményeket szeretnének kapni.
A Shake feltételezi, hogy a tesztek a fönti forgatókönyv alapján készültek, de ehhez egy olyan átlátható test engine-t ad, amellyel "batch mode"-ban is lehetséges a tesztek végrehajtása, illetve átfogó képet lehet kapni a különböző erdeményekről. Addig, amig a tesztek assert()-et hívnak, a Shake kellően sok információt tud szerezni a forráskódból illetve a futási idejű végrehajtásból. Ezt a tesztek forráskódjának preprocesszálásával éri el a Leg segítségével. Minden assert() hívást lecserél egy olyanra, amellyel információt tud nyerni a kifejezésekről, értékekről és operátorokról, ami részt vesznek az assertionben.
Ha van egy installált modulunk mint például a LuaFileSystem, és belemegyünk a /tests könyvtárába, innen már futtathatjuk a Shake-et:
>>>>~/workspace/luafilesystem/tests$ shake
-> test.lua OK!
_________________
Tests: 27
Failures: 0
Errors: 0
Másrészről, ha van egy a lentihez hasonló teszt scriptünk, amely 2 assertiont tartalmaz és bukni fog:
1 items = 10
2 -- checks the correct case
3 assert (items == 10, "this should not fail")
4
5 items = 20
6 -- checks an overflow case
7 assert (items == 10, "wrong number of items")
8
9 print("Verifying the total")
10 items = 10
11 total = 30
12 assert (items == total, "wrong total")
A Shake regisztrálja a teszt bukásait, de végigfuttatja a teljes scriptet és csak a legvégén riportál:
:~/workspace$ shake
---------------- test.lua failed! ----------------
-- checks an overflow case
#7 assert (items == 10, "wrong number of items")
items -> 20
Verifying the total
#12 assert (items == total, "wrong total")
items -> 10
total -> 30
_________________
Tests: 3
Failures: 2
Errors: 0
Figyeljük meg, mennyivel informatívabb lesz ez, mint a default kimenet, a teszt script Lua-val való futtatásakor.
:~/workspace$ lua5.1 test.lua
lua5.1: test.lua:7: wrong number of items
stack traceback:
[C]: in function 'assert'
test.lua:7: in main chunk
[C]: ?
Busted
A Busted lényege a könnyű használat - persze főként azok számára, akik használtak már néhány unit teszt framework-öt. lua >= 5.1, moonscript, és LuaJIT >= 2.0.0-t mellett működik. Remekül dokumentált, testreszabható és sok lehetőséget rejt magában (alternatív nyelvi csomagokat is támogat!). Támogat továbbá többféle assert-et, mock-okat és spy-okat, error trapping-et.
Íme egy példa az eredti dokumentációból:
describe("Busted unit testing framework", function()
describe("should be awesome", function()
it("should be easy to use", function()
assert.truthy("Yup.")
end)
it("should have lots of features", function()
-- deep check comparisons!
assert.are.same({ table = "great"}, { table = "great" })
-- or check by reference!
assert.are_not.equal({ table = "great"}, { table = "great"})
assert.truthy("this is a string") -- truthy: not false or nil
assert.True(1 == 1)
assert.is_true(1 == 1)
assert.falsy(nil)
assert.has_error(function() error("Wat") end, "Wat")
end)
it("should provide some shortcuts to common functions", function()
assert.are.unique({{ thing = 1 }, { thing = 2 }, { thing = 3 }})
end)
it("should have mocks and spies for functional tests", function()
local thing = require("thing_module")
spy.on(thing, "greet")
thing.greet("Hi!")
assert.spy(thing.greet).was.called()
assert.spy(thing.greet).was.called_with("Hi!")
end)
end)
end)
A teszt elkészítésének lépései a következők:
- Készítsünk egy spec könyvtárat a repository-nkba
- Írjuk meg a module_spec.lua file-okat - ezek tartalmazzák a unit teszteket, osztályokra bontva, ill. egyéb módon tagolva
- Futassuk a busted-dal a projekt root könyvtárából.
LUnit
Az LUnit egy kompakt unit testing eszköz legalább 5.1-es Luához. Egy shell scriptből és két Lua modulból áll. A tesztek futtatásához a scriptet kell
használni, a teszteket tartalmazó lua fájlt megadva paraméterként. Az egyes teszteknek a „test” prefixxel vagy suffixxel rendelkező paraméter nélküli
függvénynek kell lenniük. A könyvtár 27 assert és 8 típusellenőrő metódust tartalmaz.
Assert metódusok:
Ezek valamilyen állítás ellenőrzésére szolgálnak. Ha a feltétel teljesül, akkor sikeresen lefutnak, ha nem, akkor hibát jeleznek
fail:
Mindenképpen hibát jelez.
assert:
Sikeres, ha a paraméter nem hamis vagy nil
assert_true
Sikeres, ha a paraméter igaz.
assert_false
Sikeres, ha a paraméter hamis.
assert_equal
Sikeres, ha a paraméterek egyenlőek.
assert_not_equal
Sikeres, ha a paraméterek nem egyenlőek.
assert_match
Sikeres, ha az első paraméter illeszkedik a másodikban megadott mintára.
assert_not_match
Sikeres, ha az első paraméter nem illeszkedik a másodikban megadott mintára.
assert_nil
Sikeres, ha a paraméterben megadott érték nil.
assert_not_nil
Sikeres, ha a paraméterben megadott érték nem nil.
assert_boolean
assert_not_boolean
assert_number
assert_not_number
assert_string
assert_not_string
assert_table
assert_not_table
assert_function
assert_not_function
assert_thread
assert_not_thread
assert_userdata
assert_not_userdata
Sikeresek, ha a paraméter megfelel a névből magától értetődő típusmegkötésnek.
assert_error
Sikeres, ha a paraméterben megadott függvény hibát dob.
assert_pass
Sikeres, ha a paraméterben megadott függvény hiba nélkül lefut
Típusellenőrző metódusok:
is_nil
is_boolean
is_number
is_string
is_table
is_function
is_thread
is_userdata
Ezek igazat adnak, ha a paraméter megfelelő típusú, egyébként hamisat.