lunarmodules / busted Goto Github PK
View Code? Open in Web Editor NEWElegant Lua unit testing.
Home Page: https://lunarmodules.github.io/busted/
License: MIT License
Elegant Lua unit testing.
Home Page: https://lunarmodules.github.io/busted/
License: MIT License
I'm using the "uci" library in two different spec files, and in one of them I set the path in a setup() call. This works well, but the uci library is not reloaded when the second spec file is run, and the path remains changed as set in the first file.
I can save and restore the path in the teardown call, but I'd like each test (file) to be run in isolation if possible.
The private example using _TEST uses the method of returning a table of functions to be a module, rather than the module(...,package.seeall) method.
how can I test privates this way? Is it even possible?
It seems busted does not run with LuaJIT-2 when 5.2 compatibility is used:
$ busted -l /home/nino/Downloads/LuaJIT-2.0.0-beta10/src/luajit spec/core_spec.lua
joined value: /home/nino/prog/busted/
/home/nino/Downloads/LuaJIT-2.0.0-beta10/src/luajit: /usr/local/share/lua/5.1/busted/busted.lua:86: attempt to yield across C-call boundary
stack traceback:
[C]: in function 'yield'
/usr/local/share/lua/5.1/busted/busted.lua:86: in function 'run_context'
/usr/local/share/lua/5.1/busted/busted.lua:126: in function 'busted'
busted_bootstrap:140: in main chunk
[C]: ?
This is when LuaJIT is compiled with 5.2 compatibility on:
make XCFLAGS=-DLUAJIT_ENABLE_LUA52COMPAT
It works fine when it's compiled without this option. I tested both beta 9 and beta 10 with the same result. I attempted to check lua 5.2 itself, but couldn't get a good environment up on account of luarocks.org being down.
(This is against the rocks-installed 1.1.1, I haven't checked master).
Hi,
I currently use Yet Another Class Implementation for my devs ans I store the classes in a table to look like namespaces.
bonsai = {}
bonsai.Tree = newclass( "bonsai.Tree" )
function bonsai.Tree:doSomething()
return "Whisper"
end
If I try to make some tests, I add this kind of piece of code:
require "busted"
require "tree"
describe("Unit tests for bonsai.String", function()
it("A first test", function()
local tree = bonsai.Tree()
local say = tree:doSomething()
local a = { test = say }
local b = { test = "Whisper" }
assert.same( a, b )
end)
end)
I got this kind of error:
attempt to index global 'bonsai' (a nil value)
And I don't know how to handle this with busted (I haven't seen such exemples on your website).
I begin with Lua and it would be usefull to add more complexe exemples.
i need to make a stub for a function and use it in some tests, and then use function as normal. It may look like:
Describe A
Setup A
stub(f_A)
It A
f_A()
Describe B
It B
f_A()
Now, then i run It B
the stub is called, not a real function. So is there a way to make stub local to block or to destroy it?
Hi there, example as is presented in doc, doesnot work
describe("spies", function()
it("registers a new spy as a callback", function()
local s = spy.new()
s(1, 2, 3)
s(4, 5, 6)
assert.spy(s).was.called()
assert.spy(s).was.called(2) -- twice!
assert.spy(s).was.called_with({1, 2, 3}) -- checks the history
end)
It ends with
error:/usr/local/share/lua/5.1/luassert/assert.lua:12:
Perhaps there could be a flag that enables printing the traceback upon a failed test that errors unexpectedly?
Right now I only get the single error line when something goes wrong in my code, but I think more context such as the traceback could be useful.
Failure → src/test.lua @ 35
LOADK - Boolean
./src/main.lua:71: attempt to perform arithmetic on local 'd' (a nil value)
Since this is inside of a function I use everywhere, I believe a little more context would help actually resolve it.
hi, I've found problem with false positive test
function return_nil() return nil end
describe('testing grammar', function()
it('identifiers', function()
assert.is.equal('123', return_nil())
end)
end)
Re issue #53
it("should have mocks and spies for funcitonal tests", funciton()
The line above has 2 typos, 1 in the string literal, 1 in the function() keyword at the end
(sorry for the brevity/lacking pull request, doing this on my android phone)
PS. Looking great! I'm looking forward to giving this a spin!
With multiple nested describe blocks in my tests, I can't get that information in the custom output.
It's in the context_tree passed to header/footer, but not in the status or options blobs pased to formatted_status.
I'm trying to generated junit compatible xml, and it works now, but it's very flat only having access to the final test name from the it() call.
I'm calling this a "possible bug" since I'm not sure whether it's indeed a bug or me missing something.
➜ mkdir test_require_inside_busted
➜ cd test_require_inside_busted
➜ test_require_inside_busted$ mkdir spec
➜ test_require_inside_busted$ touch foo.lua
➜ test_require_inside_busted$ touch spec/foo_spec.lua
➜ test_require_inside_busted$ echo 'local foo = require "foo"' >> spec/foo_spec.lua
➜ test_require_inside_busted$ tree .
.
├── foo.lua
└── spec
└── foo_spec.lua
1 directory, 2 files
➜ test_require_inside_busted$ busted spec/foo_spec.lua
joined value: /absolute/path/to/test_require_inside_busted/
An error occurred while loading a test::...ing/lua/test_require_inside_busted/spec/foo_spec.lua:1: module 'foo' not found:
no field package.preload['foo']
no file './foo.lua'
no file '/usr/local/share/lua/5.1/foo.lua'
no file '/usr/local/share/lua/5.1/foo/init.lua'
no file '/usr/local/lib/lua/5.1/foo.lua'
no file '/usr/local/lib/lua/5.1/foo/init.lua'
no file './foo.so'
no file '/usr/local/lib/lua/5.1/foo.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
0 successes / 0 failures / 0 pending : 1.4e-05 seconds.
On the previous example, I would expect require 'foo'
to be valid. Insted, I get an error complaining that foo isn't found. The error message lists './foo.lua' as non-existing, even when it's clearly there.
I'm opening this issue to enquire about the usage of coroutines in bin/busted_bootstrap and core.lua.
I'm starting to think that the code would be simpler with plain tables and functions. As far as I know, coroutines will not make the code go any faster - if anything, they will make it a little slower, for the context switches. But it will still be single-threaded, and they will still be executed sequentially.
The _TEST global is only visible inside of a test (inside an it()
callback).
It should be visible at the global level (i.e. when I require "mylib"
at the top of the file, or inside a describe()
)
::Feature Request::
(Depends on threaded tests feature)
Doing a require 'busted'
does not work as Luarocks installs it into /usr/[local/]share/busted/busted.lua
so instead I have to do:
require 'busted/busted'
It isn't really a big deal, but maybe you can make the entry script requirable directly, which in turn can require the rest properly with the folder prefixed. Then users can do require 'busted'
and that script requires the rest of what the library needs.
Just a thought.
The output code calls an undefined function; error_description(status, options)
@line https://github.com/Olivine-Labs/busted/blob/master/src/output/TAP.lua#L66
lua: C:\Users\Public\Lua\5.1\lua\busted\output\TAP.lua:66: attempt to call global 'error_description' (a nil value) stack traceback: C:\Users\Public\Lua\5.1\lua\busted\output\TAP.lua:66: in function (tail call): ? C:\Users\Public\Lua\5.1\lua\busted\core.lua:272: in function 'busted' C:\Users\Public\Lua\5.1\busted_bootstrap:107: in main chunk [C]: ?
An unknown assertion => 0 failures.
C:\Users\Thijs\Dropbox\Lua projects\busted\luassert>busted spec An error occurred while loading a test::...ox\Lua projects\busted\luassert\spec\readme_spec.lua:3: luassert: unknown modifier/assertion: 'True' ++++++++++++++++++++++ 22 successes, 0 failures, and 0 pending in 0.012 seconds.
A testfile compilation error => 0 failures.
C:\Users\Thijs\Dropbox\Lua projects\busted\luassert>busted spec An error occurred while loading a test::C:\Users\Thijs\Dropbox\Lua projects\busted\luassert\spec\readme_spec.lua:3: '' expected near 'true' ++++++++++++++++++++++ 22 successes, 0 failures, and 0 pending in 0.011 seconds.
Lua 5.14
LuaRocks 2.0.10
1st error involves failed compilation of LuaFileSystem (what version of C++ is required here?)
2nd error: Could not satisfy dependency: say >= 1.1-1
Currently the site says:
s:set("en", "assertion.has_property.positive", "Expected property %s in:\n%s")
s:set("en", "assertion.has_property.negative", "Expected property %s to not be in:\n%s")
assert:register("assertion", "has_property", has_property, "assertion.has_property.positive",, "assertion.has_property.negative")
Where it should say:
say:set_namespace("en")
say:set("assertion.has_property.positive", "Expected property %s in:\n%s")
say:set("assertion.has_property.negative", "Expected property %s to not be in:\n%s")
assert:register("assertion", "has_property", has_property, "assertion.has_property.positive", "assertion.has_property.negative")
When I have an assert.equals
does not blow up when comparing any value with a nil.
describe("bad stuff happens", function()
it("does not blows up", function()
local result = {}
assert.equal(result.a, "asdf")
assert.equal(nil, "asdf")
end)
it("does not blows up", function()
local result = {}
assert.equal("asdf", result.a)
assert.equal("asdf", nil)
end)
end)
I would expect each one of those assertions to blow up.
Just for verification from lua REPL.
> print("asdf"==nil)
false
I'm thinking the rockspec in the repository should point to the repository itself.
version = "HEAD-0"
source = {
url = "git://github.com/daurnimator/busted.git" ;
}
file needs to be renamed to busted-HEAD-0.rockspec
Adding a version or static download should only be done on release.
Here're the test:
➜ lua busted --version
busted: error: missing required arguments; re-run with --help for usage.
➜ lua busted --version foo
busted: version 1.1.0
I would recommend having the version in one single file and pull the text from there when needed (don't know if the rockspec admits such thing though)
Hi,
I installed luarocks manualy on my Ubuntu 12.04 (version provided by Canonical is older) and tryed to install busted :
sudo luarocks install busted
And got the following output :
Installing http://luarocks.org/repositories/rocks/busted-1.1-1.src.rock...
Using http://luarocks.org/repositories/rocks/busted-1.1-1.src.rock... switching to 'build' mode
Archive: /tmp/luarocks_luarocks-rock-busted-1.1-1-1634/busted-1.1-1.src.rock
inflating: busted-1.1-1.rockspec
inflating: busted-1.1.tar.gz
Updating manifest for /usr/local/lib/luarocks/rocks
busted 1.1-1 is now built and installed in /usr/local/ (license: MIT <http://opensource.org/licenses/MIT>)
But when I try to run busted
I have the following errors :
/usr/local/bin/busted: 2: /usr/local/bin/busted: Bad substitution
/usr/local/bin/busted: 1: /usr/local/bin/busted: cygpath: not found
/usr/local/bin/busted: 1: /usr/local/bin/busted: cygpath: not found
/usr/local/bin/busted_bootstrap: 1: /usr/local/bin/busted_bootstrap: --: not found
/usr/local/bin/busted_bootstrap: 2: local: not in a function
Is there some extra steps for Ubuntu ?
Mocha provides an optional done method to each "before" and "it" which allows async test.
Since Lua lacks Javascript Functions's length (for introspecting the callback at runtime) the interface must be different somehow. Maybe like this
before(function(done)
ev.Timer.new(function()
assert.is_true(true)
done()
end,0.1):start(loop)
return true -- returning truthy indicates to wait for done to be called
end)
Further the busted executable should somehow start the event loop
loop:loop()
For node.js this is obviously far easier to achieve, but it would be really nice, since Lua + lua-ev is a charming combination for environments, where node.js is not availble (embedded devices).
I installed busted via luarocks on Ubuntu 12.10. When I run it on a simple test called test_spec.lua under folder spec.
require("busted")
describe("some assertions", function()
it("tests positive assertions", function()
assert.is.true(true)
assert.true(true)
assert.are.equal(1, 1)
assert.has.errors(function() error("this should fail") end)
end)
it("tests negative assertions", function()
assert.is_not.true(false)
assert.are_not.equals(1, "1")
assert.has_no.errors(function() end())
end)
end)
When I run busted on this folder I get the following error.
An error occurred while loading a test::spec/test_spec.lua:5: '<name>' expected near 'true'
0 successes / 0 failures / 0 pending : 0 seconds.
require("busted")
describe("Latest busted from Luarocks", function()
it("seems to have a problem with is", function()
assert.is_true(1 == 2)
end)
it("isn't limited to true", function()
assert.is_false(2 == 2)
end)
it("doesn't have that problem with True", function()
assert.True(1 == 2)
end)
it("does not have a problem with is.True, either", function()
assert.is.True(1 == 2)
end)
end)
2 successes / 2 failures / 0 pending : 0 seconds.
Failure → busted-test.lua @ 10
doesn't have that problem with True
busted-test.lua:11: Expected objects to be the same. Passed in:
(boolean) false
Expected:
(boolean) true
Failure → busted-test.lua @ 13
does not have a problem with is.True
busted-test.lua:14: Expected objects to be the same. Passed in:
(boolean) false
Expected:
(boolean) true
The main site (http://olivinelabs.com/busted/) uses a menu that moves along when scrolling the content.
If you have a small screen (mobile phone) the menu will block the content (hover over it)
The horizontal move should be disabled, vertical only should be used.
to mimic behaviour, on a PC, resize the browser window to a small width, then use the horizontal scrollbar to move to the right. The menu will move along and hide the content.
after adding assertion like this:
assert.spy(xxx.yyy).was_called_with('application/json', 'begun')
i got this error:
lua: ...r/local/share/lua/5.1/busted/output/utf_terminal.lua:22: attempt to concatenate field 'err' (a table value)
stack traceback:
...r/local/share/lua/5.1/busted/output/utf_terminal.lua:22: in function 'error_description'
...r/local/share/lua/5.1/busted/output/utf_terminal.lua:97: in function 'format_statuses'
...r/local/share/lua/5.1/busted/output/utf_terminal.lua:135: in function 'formatted_status'
/usr/local/share/lua/5.1/busted/core.lua:175: in function 'busted'
/usr/local/bin/busted_bootstrap:176: in main chunk
[C]: ?
busted version 1.4
kinda hard to generate closing tags in xml :)
::Feature Request::
The end result of this feature will make test run time only take as long as the longest running test file, it will add valuable new features necessary for asyncronous testing, and it will allow us to add an entirely new class of tests, performance tests.
what does this code do?
elseif match then
test(description, callback)
end
I cannot find the definition of test()
, so it seems the code never gets hit.
I don't see a way to randomize the order that tests run in. Is this currently possible?
I tried the code from the documentation
describe("stubs", function()
it("replaces an original function", function()
local t = {
greet = function(msg) print(msg) end
}
stub(t, "greet")
t.greet("Hey!") -- DOES NOT print 'Hey!'
assert.spy(t.greet).was.called_with("Hey!")
end)
end)
but all I get is
Failure → spec/test_spec.lua @ 7
replaces an original function
spec/test_spec.lua:12: attempt to call global 'stub' (a nil value)
Testing the following code;
require("busted") local ctr -- start tests describe("Level A", function() setup(function() ctr = 0 print("setup A") end) teardown(function() print("teardown A") end) before_each(function() ctr = math.abs(ctr) + 1 print("before_each A", ctr) end) after_each(function() ctr = -ctr print("after_each A", ctr) end) it("tests A one", function() print("test A one", ctr) end) it("tests A two", function() print("test A two", ctr) end) describe("Level B", function() it("tests B one", function() print("test B one", ctr) end) it("tests B two", function() print("test B two", ctr) end) end) end)
Results in this output;
setup A before_each A 1 test A one 1 after_each A -1 before_each A 2 test A two 2 after_each A -2 before_each A 3 after_each A -3 teardown A test B one -3 test B two -3
Issues:
1 - before_each and after_each run once too many (3/-3 on the A level)
2 - I would have expected the 'Level A Teardown' to run AFTER level B was completed
3 - I would have expected the before_each and after_each of level A, to be hierarchical, so they would also be applied to Level B
I have something like this...
describe("Simple tests", function() local postman before_each(function() postman = Plugin.blah:new({settings_for_plugin}) end) it("Some big complicated test", function() -- lots and lots of tests on some data generating end) it("More big complicated test", function() -- lots and lots of tests on some data generating end) end)
I have multiple plugins that should behave the same way for the same input/outputs. I'd like to run all the tests in a describe() blob again, but with a different before_each() getting called. Any ideas on how to do this, or if it's possible without duplicating the tests?
'true' is a keyword;
hence assert.true(1 == 1)
is not valid code.
I have my lua files in "lualib" rather than "src" (for mathching some other tools) and have tried the following...
busted --lpath="./lualib/?.lua;./lualib/?/?.lua"
and
busted -m "./lualib/?.lua;./lualib/?/?.lua"
but in both cases, the tests are found, but is not set properly, it still looks in src/.
An error occurred while loading a test::spec/remake.utils_spec.lua:3: module 'remake.utils' not found:
no field package.preload['remake.utils']
no file 'src/remake/utils.lua'
no file 'src/remake/utils/remake/utils.lua'
no file 'src/remake/utils/init.lua'
no file './remake/utils.lua'
no file '/usr/share/lua/5.1/remake/utils.lua'
no file '/usr/share/lua/5.1/remake/utils/init.lua'
no file '/usr/lib64/lua/5.1/remake/utils.lua'
no file '/usr/lib64/lua/5.1/remake/utils/init.lua'
no file './remake/utils.so'
no file '/usr/lib64/lua/5.1/remake/utils.so'
no file '/usr/lib64/lua/5.1/loadall.so'
no file './remake.so'
no file '/usr/lib64/lua/5.1/remake.so'
no file '/usr/lib64/lua/5.1/loadall.so'
The file it's trying to find is in lualib/remake/utils.lua. Adding a symlink "src" for lualib works fine, but isn't really something I want to do.
Busted version 1.4, installed via luarocks.
Tests shouldn't need to require "busted"
Add it into the package.preload
table.
It needs a comma between each block. Example output below (from busted -o json)
{"type":"success","description":"should make diff uuids","info":{"linedefined":6,"source":"@spec/remake.utils_spec.lua","short_src":"spec/remake.utils_spec.lua"}}{"type":"success","description":"should be able to make uuids","info":{"linedefined":11,"source":"@spec/remake.utils_spec.lua","short_src":"spec/remake.utils_spec.lua"}}
add this to an existing test file;
before_each(function() local this = "something" * wrong end)
and busted will crash because it will not catch the error. Couldn't pinpoint exactly where to fix, hence no code attached...
probably best to check the others (setup, teardown, and after_each) as well.
I just came across a weird bug when doing string comparisons. My assert looks like
assert.are.same(attack.key, "scratch")
which produces the following output
spec/Attack_spec.lua:23: Expected objects to be the same. Passed in:
(string) 'scratch'
Expected:
(string) 'scratch'
But when I change the assert order to be
assert.are.same("scratch", attack.key)
I get
spec/Attack_spec.lua:23: Expected objects to be the same. Passed in:
(nil)
Expected:
(string) 'scratch'
So it looks like there is a minor bug with string comparisons with nil.
If a test file is run, and it didn't add any results, a warning should be given because something is wrong.
I think we should show the number of pending tests, like we do now, if a test file is run that contains only pending tests. If no tests are found in a file, we should throw a warning.
We can optionally show extra information when verbose output is selected.
We should not warn on empty describe blocks, however.
Either of them will not be executed if they are not wrapped in at least one describe() level.
So either they should be called, or an error should be thrown.
Possible related installation issue: luarocks/luarocks#94
Going through the "spy" example in the Busted docs, when I intentionally call t.greet with an incorrect argument, the test still passes.
it("that replace an original function", function()
local t = {
greet = function(msg) print(msg) end
}
spy.on(t, "greet")
t.greet("You shall not pass")
assert.spy(t.greet).was_called_with("Hey!")
end)
results in a success
When I have a syntax error in a lua file, it prints out a plain white error, but then shows the regular, "elegant" busted colour output, indicating no errors. I don't think this is good enough. I think it should fail more visibly.
$ busted
An error occurred while loading a test::error loading module 'wop.security' from file 'src/wop/security.lua':
src/wop/security.lua:130: '' expected near 'end'
●●●●●●●
7 successes / 0 failures / 0 pending : 0 seconds.
$
@DorianGray mentions in #24:
We want to eventually have threaded tests. I went ahead and broke the logic out into coroutines to separate the code, and also to learn coroutines! Hopefully lualanes will eventually replace the pcalls and the coroutines so that each describe block can exist in it's own thread. Then, the tests will only run as slow as the slowest test and not an addition of all the run-times of all the tests combined.
I have first and second hand experience with large installations with many thousands of tests in several languages and it kills developer productivity when tests take forever.
While I agree with the sentiment (slow tests = bad) I'm opening this issue to express my disagreement on the implementation.
I don't think buste should be "threaded by default". My main reason is that my tests usually require some kind of shared state, like so:
describe("A non-threadable test", function()
local counter -- this variable is shared among all tests on this block
before_each(function()
counter = 0 -- always reset the shared state to a known state
end)
it("can increase the counter", function()
counter = counter + 1
assert.equals(1, counter)
end)
it("can decrease the counter", function()
counter = counter - 1
assert.equals(-1, counter)
end)
end)
The test case above runs fine in single-threaded mode. Even if the order of the tests is randomized, it will still pass. But it can fail randomly if the two tests are run in parallel. This would surprise most people coming from other testing libraries.
Note that while in this case I'm using a local variable to represent shared state, in other cases it's an external element, such a library, over which I might not have full control of - more notably, it might not be multi-thread capable.
I'm not 100% sure of how other libraries deal with multi-threading, but I think the cautious thing would be using a separate syntax for those tests that could be run in paralel. For example via a new multi_threaded
method:
describe("A multi-threaded test", function()
function createCounter()
return 0
end
multi_threaded(function()
it("can increase the counter", function()
counter = createCounter()
assert.equals(1, counter)
end)
it("can decrease the counter", function()
counter = createCounter()
assert.equals(-1, counter)
end)
end)
end)
Something explicit like this will ensure that the programmer "declares that he knows where he's running into" , so multi-threading doesn't take him "by surprise".
Using brew on Mac OSX, I've installed luarocks
. Then using luarocks
on command line ran luarocks install busted
.
The luafilesystem-1.5.0-3.rockspec
fails because it requires a version of Lua >= 5.1, < 5.2. Is this a dependency that can be fixed on busted or does luafilesystem
need to be updated?
Add a .busted file to project root and load predefined tasks. Have the ability to preset command line flags, and override them when run.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.