Last active
December 10, 2015 22:28
-
-
Save lipp/4502382 to your computer and use it in GitHub Desktop.
busted mockup for async tests with e.g. lua-ev providing:
describe,before,before_each,it clone and run locally: lua async_spec.lua; lua sync_spec.lua;
lua copas_spec.lua;
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package.path = './?.lua;'..package.path | |
local ev = require'ev' | |
local loop = ev.Loop.default | |
require'busted' | |
describe( | |
'All async in this context', | |
function() | |
before( | |
async, | |
function(done) | |
local count = 0 | |
ev.Timer.new( | |
function(loop,io) | |
count = count + 1 | |
print('before',count) | |
if count == 3 then | |
print('lets start') | |
io:stop(loop) | |
done() | |
end | |
end,0.1,0.1):start(loop) | |
end) | |
before_each( | |
async, | |
function(done) | |
ev.Timer.new( | |
function() | |
print('before_each') | |
done() | |
end,0.01):start(loop) | |
end) | |
it( | |
'async test', | |
async, | |
function(done) | |
local timer = ev.Timer.new( | |
function() | |
assert.is_truthy(true) | |
done() | |
end,0.2) | |
timer:start(loop) | |
end) | |
it( | |
'async test 2', | |
async, | |
function(done) | |
local timer = ev.Timer.new( | |
function() | |
assert.is_truthy(false) | |
assert.is_truthy(true) | |
done() | |
end,0.2) | |
timer:start(loop) | |
end) | |
it( | |
'should epic fail', | |
async, | |
function(done) | |
does_not_exist.foo = 3 | |
end) | |
it( | |
'spies work', | |
function() | |
local thing = { | |
greet = function() | |
end | |
} | |
print('SPY',spy) | |
for k,v in pairs(spy) do | |
print(k,v) | |
end | |
spy.on(thing, "greet") | |
thing.greet("Hi!") | |
assert.spy(thing.greet).was.called() | |
assert.spy(thing.greet).was.called_with("Hi!") | |
end) | |
describe( | |
'with nested contexts', | |
function() | |
before( | |
async, | |
function(done) | |
print('before in nested') | |
done() | |
end) | |
it( | |
'a nested test', | |
async, | |
function(done) | |
print('NESTED TEST') | |
local timer = ev.Timer.new( | |
function() | |
print('NESTED TEST BAKS') | |
assert.is_truthy('horst') | |
assert.is_truthy(true) | |
assert.is_truthy(true) | |
done() | |
end,0.2) | |
timer:start(loop) | |
end) | |
end) | |
end) | |
busted.run('ev',loop) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- busted maock up with async support | |
require'pl' -- for pretty.write table formating | |
assert = require'luassert' | |
spy = require('luassert.spy') | |
mock = require('luassert.mock') | |
stub = require('luassert.stub') | |
local assert_call = getmetatable(assert.is_truthy).__call | |
local push = table.insert | |
local root_context = {parents = {}} | |
local tests = {} | |
local done = {} | |
local started = {} | |
busted = {} | |
local last_test = 1 | |
local next_test | |
next_test = function() | |
if #done < #tests then | |
if not done[last_test] and not started[last_test] then | |
local test = tests[last_test] | |
if test.context then | |
if test.context.before and not test.context.before_done then | |
test.context.before( | |
function() | |
test.context.before_done = true | |
next_test() | |
end) | |
return | |
end | |
if test.context.before_each and test.context.last_before ~= last_test then | |
test.context.last_before = last_test | |
test.context.before_each(next_test) | |
return | |
end | |
end | |
test.status = { | |
description = test.name, | |
info = test.info, | |
trace = '' | |
} | |
test.info = nil | |
local new_env = {} | |
setmetatable(new_env,{__index = _G}) | |
-- this part is nasty! | |
-- intercept all calls to luasser states / proxies. | |
-- uses much of internal knowlage of luassert!!!! | |
-- the metatable of is_truthy is the same as for other | |
-- luasserts. | |
getmetatable(new_env.assert.is_truthy).__call = function(...) | |
local results = {pcall(assert_call,...)} | |
local args = {...} | |
local is_proxy = true | |
-- ducktype if this is an assertion 'result' and not a proxy | |
for k,v in pairs(args[1] or {}) do | |
if k == 'positive_message' or k == 'negative_message' then | |
is_proxy = false | |
end | |
end | |
if is_proxy then | |
return unpack(results,2) | |
else | |
if results[1] and not test.status.type then | |
test.status.type = 'success' | |
elseif not results[1] and test.status.type ~= 'failure' then | |
test.status.trace = debug.traceback("", 2) | |
test.status.type = 'failure' | |
print(test.status.type) | |
test.status.err = results[2] | |
end | |
end | |
end | |
-- not sure if this is needed yet... | |
-- new_env.pcall = function(...) | |
-- local ok,err = pcall(...) | |
-- if not ok then | |
-- test.status.type = 'failure' | |
-- test.status.err = err | |
-- end | |
-- end | |
setfenv(test.f,new_env) | |
local done = function() | |
done[last_test] = true | |
last_test = last_test + 1 | |
next_test() | |
end | |
started[last_test] = true | |
local ok,err = pcall(test.f,done) | |
if not ok then | |
if type(err) == "table" then | |
err = pretty.write(err) | |
end | |
test.status.err = err | |
done() | |
end | |
end | |
end | |
end | |
local current_context = root_context | |
busted.describe = function(desc,more) | |
local parents = {} | |
for i,parent in ipairs(current_context.parents) do | |
parents[i] = parent | |
end | |
push(parents,current_context) | |
local context = { | |
desc = desc, | |
parents = parents | |
} | |
current_context = context | |
more() | |
end | |
busted.before = function(sync_before,async_before) | |
if async_before then | |
current_context.before = async_before | |
else | |
current_context.before = function(done) | |
sync_before() | |
done() | |
end | |
end | |
end | |
busted.before_each = function(sync_before,async_before) | |
if async_before then | |
current_context.before_each = async_before | |
else | |
current_context.before_each = function(done) | |
sync_before() | |
done() | |
end | |
end | |
end | |
busted.it = function(name,sync_test,async_test) | |
local test = {} | |
test.context = current_context | |
test.name = name | |
local debug_info | |
if async_test then | |
debug_info = debug.getinfo(async_test) | |
test.f = async_test | |
else | |
debug_info = debug.getinfo(sync_test) | |
-- make sync test run async | |
test.f = function(done) | |
setfenv(sync_test,getfenv(1)) | |
sync_test() | |
done() | |
end | |
end | |
test.info = { | |
source = debug_info.source, | |
short_src = debug_info.short_src, | |
linedefined = debug_info.linedefined, | |
} | |
tests[#tests+1] = test | |
end | |
local report = function() | |
for _,test in ipairs(tests) do | |
print(pretty.write(test.status)) | |
end | |
end | |
busted.run = function(type,...) | |
local args = {...} | |
if not type then | |
next_test() | |
elseif type == 'ev' then | |
local loop = args[1] | |
local ev = require'ev' | |
ev.Timer.new(next_test,0.0001):start(loop) | |
loop:loop() | |
elseif type == 'copas' then | |
local copas = require'copas' | |
copas.addthread( | |
function() | |
repeat | |
next_test() | |
copas.step(0) | |
until #done == #tests | |
end) | |
end | |
for _,test in ipairs(tests) do | |
if test.status.type ~= 'success' and not test.status.err then | |
test.status.type = 'failure' | |
test.status.err = 'No assertions made' | |
test.status.trace = '' | |
end | |
end | |
report() | |
end | |
it = busted.it | |
describe = busted.describe | |
before = busted.before | |
before_each = busted.before_each | |
return busted |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package.path = './?.lua;'..package.path | |
local copas = require'copas' | |
local socket = require'socket' | |
require'busted' | |
local port = 19281 | |
describe( | |
'When someone connects to echo server', | |
function() | |
before( | |
async, | |
function(done) | |
copas.addserver( | |
socket.bind('*',port), | |
function(skt) | |
print('new client') | |
while true do | |
local data = copas.receive(skt) | |
if not data then | |
return | |
end | |
copas.send(skt,data..'\n') | |
end | |
end) | |
done() | |
end) | |
before_each( | |
async, | |
function(done) | |
print('before each async') | |
done() | |
end) | |
it( | |
'sent messages and maing bad test fails', | |
async, | |
function(done) | |
print('A') | |
copas.addthread( | |
function() | |
local s = socket.connect('localhost',port) | |
s:settimeout(0) | |
local client = copas.wrap(s) | |
local msg = 'HALLO' | |
client:send(msg..'\n') | |
client:receive('*l') | |
s:close() | |
assert.is_truthy(false) | |
assert.is_truthy(false) | |
print('F A') | |
done() | |
end) | |
end) | |
it( | |
'sent messages are echoed correctly', | |
async, | |
function(done) | |
print('B') | |
copas.addthread( | |
function() | |
local s = socket.connect('localhost',port) | |
s:settimeout(0) | |
local client = copas.wrap(s) | |
local msg = 'HALLO' | |
client:send(msg..'\n') | |
local echoed = client:receive('*l') | |
s:close() | |
assert.is_truthy(echoed == msg) | |
print('F B') | |
done() | |
end) | |
end) | |
it( | |
'sent messages are echoed correctly with two clients', | |
async, | |
function(done) | |
local other_finished | |
copas.addthread( | |
function() | |
local s = socket.connect('localhost',port) | |
s:settimeout(0) | |
local client = copas.wrap(s) | |
local msg = 'HALLO' | |
client:send(msg..'\n') | |
local echoed = client:receive('*l') | |
s:close() | |
assert.is_truthy(echoed == msg) | |
if other_finished then | |
done() | |
else | |
other_finished = true | |
end | |
end) | |
copas.addthread( | |
function() | |
local s = socket.connect('localhost',port) | |
s:settimeout(0) | |
local client = copas.wrap(s) | |
local msg = 'HALLO' | |
client:send(msg..'\n') | |
local echoed = client:receive('*l') | |
s:close() | |
assert.is_truthy(echoed == msg) | |
if other_finished then | |
done() | |
else | |
other_finished = true | |
end | |
end) | |
end) | |
it( | |
'this is sync though', | |
function() | |
print('sync') | |
assert.is_truthy(true) | |
assert.is_truthy(true) | |
assert.is_truthy(true) | |
end) | |
describe( | |
'deeper context', | |
function() | |
before_each( | |
function() | |
print('before each sync') | |
end) | |
it( | |
'sent messages are echoed correctly two times in a row', | |
async, | |
function(done) | |
print('DEEP') | |
copas.addthread( | |
function() | |
local s = socket.connect('localhost',port) | |
s:settimeout(0) | |
local client = copas.wrap(s) | |
local msg = 'HALLO' | |
client:send(msg..'\n') | |
local echoed = client:receive('*l') | |
assert.is_truthy(echoed == msg) | |
msg = 'HALLO again' | |
client:send(msg..'\n') | |
local echoed = client:receive('*l') | |
s:close() | |
assert.is_truthy(echoed == msg) | |
print('F DEEP') | |
done() | |
end) | |
end) | |
end) | |
end) | |
busted.run('copas') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- normal / sync test | |
package.path = './?.lua;'..package.path | |
require'busted' | |
it( | |
'sync test', | |
function(done) | |
assert.is_truthy(true) | |
end) | |
busted.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment