From 2231ae27e6d60ac81ac184fe9ff4d1034d341a0c Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Sun, 13 Jul 2014 12:27:33 -0700 Subject: [PATCH 001/293] Support for a helper (environment) script Handy for preloading things prior to tests, etc --- bin/busted | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bin/busted b/bin/busted index e4d9f3f9..aff0151f 100755 --- a/bin/busted +++ b/bin/busted @@ -37,6 +37,7 @@ cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module cli:add_option('-r, --run=RUN', 'config to run from .busted file') cli:add_option('--lang=LANG', 'language for error messages', 'en') cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) +cli:add_option('--helper=PATH', 'A helper script that is run before tests') cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') @@ -104,6 +105,10 @@ if #cliArgs.cpath > 0 then package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') end +if cliArgs.helper ~= '' then + dofile(cliArgs.helper) +end + local loaders = {} if #cliArgs.loaders > 0 then string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) From 11cf04ce3f9b22af822e30bbf8ca82db9f6eb19e Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Sun, 13 Jul 2014 13:00:43 -0700 Subject: [PATCH 002/293] `.busted` was busted --- bin/busted | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/busted b/bin/busted index e4d9f3f9..35f798b4 100755 --- a/bin/busted +++ b/bin/busted @@ -74,10 +74,12 @@ local pattern = cliArgs.pattern -- Load busted config file if available local bustedConfigFilePath = path.normpath(path.join(fpath, '.busted')) -local bustedConfigFile = pcall(function() tasks = loadfile(bustedConfigFilePath)() end) +local configTasks = {} +local bustedConfigFile = pcall(function() configTasks = loadfile(bustedConfigFilePath)() end) if bustedConfigFile then - local config, err = configLoader(bustedConfigFile, config, cliArgs) + local config, err = configLoader(configTasks, cliArgs, cliArgs.run) + cliArgs = config if err then print(err) From ae1909e527c00274eef871073037e6c986650fe3 Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Wed, 16 Jul 2014 19:14:02 -0700 Subject: [PATCH 003/293] Use cliparse's new API, and handle error cases. --- bin/busted | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/busted b/bin/busted index dafc045d..308e31d0 100755 --- a/bin/busted +++ b/bin/busted @@ -47,7 +47,10 @@ cli:add_flag('--suppress-pending', 'suppress `pending` test output') cli:add_flag('--defer-print', 'defer print to when test suite is complete') -- Parse the cli arguments -local cliArgs = cli:parse_args() +local cliArgs, error = cli:parse() +if error then + os.exit(1) +end -- Return early if only asked for the version if cliArgs.version then From 1ba552c92e431aac5cb4de329ab9bccc170469f6 Mon Sep 17 00:00:00 2001 From: Drew Date: Thu, 17 Jul 2014 22:23:34 -0700 Subject: [PATCH 004/293] fix async spec --- spec/async_spec.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/async_spec.lua b/spec/async_spec.lua index 65284aa2..d673fe9b 100644 --- a/spec/async_spec.lua +++ b/spec/async_spec.lua @@ -15,6 +15,7 @@ describe('testing the done callback with tokens', function() assert.stub(done.done_cb).was.called(1) done.done_cb:revert() -- revert so test can complete + done() end) it('Tests done call back unordered', function() @@ -31,6 +32,7 @@ describe('testing the done callback with tokens', function() assert.stub(done.done_cb).was.called(1) done.done_cb:revert() -- revert so test can complete + done() end) it('Tests done call back defaulting to ordered', function() @@ -43,6 +45,7 @@ describe('testing the done callback with tokens', function() assert.has_no_error(function() done('2') end) done.done_cb:revert() -- revert so test can complete + done() end) end) @@ -51,29 +54,34 @@ describe('testing done callbacks being provided for async tests', function() async() assert.is_table(done) assert.is_function(done.wait) + done() end) before_each(function() async() assert.is_table(done) assert.is_function(done.wait) + done() end) after_each(function() async() assert.is_table(done) assert.is_function(done.wait) + done() end) teardown(function() async() assert.is_table(done) assert.is_function(done.wait) + done() end) it('Tests done callbacks being provided for async tests', function() async() assert.is_table(done) assert.is_function(done.wait) + done() end) end) From 665dfcbab6ee25cab99b103afdbc1a952c650ce2 Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Sun, 20 Jul 2014 13:05:38 -0700 Subject: [PATCH 005/293] Handle errors in describe blocks Fixes part of #260 Also, cc @kbambz :P --- busted/outputHandlers/base.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 61290af4..bcbc8a12 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -22,6 +22,7 @@ return function(busted) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd) busted.subscribe({ 'test', 'start' }, handler.baseTestStart) busted.subscribe({ 'test', 'end' }, handler.baseTestEnd) + busted.subscribe({ 'error', 'describe' }, handler.baseError) busted.subscribe({ 'error', 'it' }, handler.baseError) busted.subscribe({ 'error', 'file' }, handler.baseError) busted.subscribe({ 'error', 'pending' }, handler.baseError) From 4351dd9d5da03fd3bc128266c6eb8bcf6c887dcc Mon Sep 17 00:00:00 2001 From: Drew Date: Sun, 27 Jul 2014 14:50:03 -0700 Subject: [PATCH 006/293] fixed a few bugs related to error reporting. Removed async and made tests pending until I can come up with a clean way of re-implementing it. Current implementation of async did not play nice with output handlers --- bin/busted | 9 +++++---- busted/init.lua | 13 ------------- spec/async_spec.lua | 4 ++-- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/bin/busted b/bin/busted index 308e31d0..a4d46dc7 100755 --- a/bin/busted +++ b/bin/busted @@ -47,8 +47,8 @@ cli:add_flag('--suppress-pending', 'suppress `pending` test output') cli:add_flag('--defer-print', 'defer print to when test suite is complete') -- Parse the cli arguments -local cliArgs, error = cli:parse() -if error then +local cliArgs, hasError = cli:parse() +if hasError then os.exit(1) end @@ -181,14 +181,16 @@ testFileLoader(rootFile, pattern) local failures = 0 local errors = 0 -busted.subscribe({ 'error' }, function() +busted.subscribe({ 'error' }, function(...) errors = errors + 1 + return nil, true end) busted.subscribe({ 'test', 'end' }, function(element, parent, status) if status == 'failure' then failures = failures + 1 end + return nil, true end) busted.publish({ 'suite', 'start' }) @@ -199,5 +201,4 @@ local exit = 0 if failures > 0 or errors > 0 then exit = 1 end - os.exit(exit) diff --git a/busted/init.lua b/busted/init.lua index 5a62c20c..c1231dc3 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -98,17 +98,6 @@ return function(busted) busted.publish({ 'test', 'end' }, pending, busted.context.parent(pending), 'pending', trace) end - local async = function() - local parent = busted.context.get() - if not parent.env then parent.env = {} end - - parent.env.done = require 'busted.done'.new(function() - busted.publish({ 'test', 'end' }, it, parent, 'success') - if finally then busted.safe('finally', finally, it) end - dexecAll('after_each', parent, true) - end) - end - busted.register('file', file) busted.register('describe', describe) @@ -117,8 +106,6 @@ return function(busted) busted.register('it', it) busted.register('pending', pending) - busted.context.get().env.async = async - busted.register('setup') busted.register('teardown') busted.register('before_each') diff --git a/spec/async_spec.lua b/spec/async_spec.lua index d673fe9b..3b4209c7 100644 --- a/spec/async_spec.lua +++ b/spec/async_spec.lua @@ -1,4 +1,4 @@ -describe('testing the done callback with tokens', function() +pending('testing the done callback with tokens', function() it('Tests done call back ordered', function() async() @@ -49,7 +49,7 @@ describe('testing the done callback with tokens', function() end) end) -describe('testing done callbacks being provided for async tests', function() +pending('testing done callbacks being provided for async tests', function() setup(function() async() assert.is_table(done) From 7557ce8487790005dd1cb997c045feecc253534f Mon Sep 17 00:00:00 2001 From: Drew Date: Sun, 27 Jul 2014 14:56:15 -0700 Subject: [PATCH 007/293] reordered bin/busted so cliargs can override more defaults from .busted --- bin/busted | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/bin/busted b/bin/busted index a4d46dc7..8567678f 100755 --- a/bin/busted +++ b/bin/busted @@ -57,25 +57,9 @@ if cliArgs.version then return print(busted.version) end -local tags = {} -local excludeTags = {} - -if cliArgs.t ~= '' then - tags = utils.split(cliArgs.t, ',') -end - -if cliArgs['exclude-tags'] ~= '' then - excludeTags = utils.split(cliArgs['exclude-tags'], ',') -end - -- Load current working directory local fpath = cliArgs.d --- Load test directory -local rootFile = path.normpath(path.join(fpath, cliArgs.ROOT)) - -local pattern = cliArgs.pattern - -- Load busted config file if available local bustedConfigFilePath = path.normpath(path.join(fpath, '.busted')) local configTasks = {} @@ -90,6 +74,22 @@ if bustedConfigFile then end end +-- Load test directory +local rootFile = path.normpath(path.join(fpath, cliArgs.ROOT)) + +local pattern = cliArgs.pattern + +local tags = {} +local excludeTags = {} + +if cliArgs.t ~= '' then + tags = utils.split(cliArgs.t, ',') +end + +if cliArgs['exclude-tags'] ~= '' then + excludeTags = utils.split(cliArgs['exclude-tags'], ',') +end + -- If coverage arg is passed in, load LuaCovsupport if cliArgs.coverage then luacov() From 810b3d878bf13bd54d235a93de379959de682960 Mon Sep 17 00:00:00 2001 From: Drew Date: Mon, 28 Jul 2014 21:53:17 -0700 Subject: [PATCH 008/293] made error event handling better --- busted/outputHandlers/base.lua | 5 +---- busted/outputHandlers/junit.lua | 1 + busted/outputHandlers/plainTerminal.lua | 1 + busted/outputHandlers/utfTerminal.lua | 1 + 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index bcbc8a12..2b4baf58 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -22,10 +22,7 @@ return function(busted) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd) busted.subscribe({ 'test', 'start' }, handler.baseTestStart) busted.subscribe({ 'test', 'end' }, handler.baseTestEnd) - busted.subscribe({ 'error', 'describe' }, handler.baseError) - busted.subscribe({ 'error', 'it' }, handler.baseError) - busted.subscribe({ 'error', 'file' }, handler.baseError) - busted.subscribe({ 'error', 'pending' }, handler.baseError) + busted.subscribe({ 'error' }, handler.baseError) end handler.getFullName = function(context) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 11bb201a..ba92acb0 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -59,6 +59,7 @@ return function(options, busted) busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) + busted.subscribe({ 'error', 'describe' }, handler.error) return handler end diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 115247c6..c7024a97 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -145,6 +145,7 @@ return function(options, busted) busted.subscribe({ 'test', 'end' }, handler.testEnd) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) + busted.subscribe({ 'error', 'describe' }, handler.error) return handler end diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 96d4a580..792f02d6 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -146,6 +146,7 @@ return function(options, busted) busted.subscribe({ 'test', 'end' }, handler.testEnd) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) + busted.subscribe({ 'error', 'describe' }, handler.error) return handler end From 6510e55dae1f18a934b9bd6f0153cc2844ee0558 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Thu, 31 Jul 2014 11:18:13 -0700 Subject: [PATCH 009/293] Fix config loader --- bin/busted | 8 ++++---- busted/modules/configuration_loader.lua | 15 +++++++++------ spec/modules/configuration_loader_spec.lua | 8 +++++--- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/bin/busted b/bin/busted index 8567678f..7174427c 100755 --- a/bin/busted +++ b/bin/busted @@ -61,13 +61,13 @@ end local fpath = cliArgs.d -- Load busted config file if available +local configFile = { } local bustedConfigFilePath = path.normpath(path.join(fpath, '.busted')) -local configTasks = {} -local bustedConfigFile = pcall(function() configTasks = loadfile(bustedConfigFilePath)() end) + +local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) if bustedConfigFile then - local config, err = configLoader(configTasks, cliArgs, cliArgs.run) - cliArgs = config + local config, err = configLoader(configFile, cliArgs) if err then print(err) diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index d5a3fe96..c6dab900 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -3,15 +3,18 @@ return function() local tablex = require 'pl.tablex' -- Function to load the .busted configuration file if available - local loadBustedConfigurationFile = function(configFile, config, run) - if run and run ~= '' then - if type(configFile) ~= 'table' then - return config, '.busted file does not return a table.' - end + local loadBustedConfigurationFile = function(configFile, config) + if type(configFile) ~= 'table' then + return config, '.busted file does not return a table.' + end + local run = config.run + + if run and run ~= '' then local runConfig = configFile[run] if type(runConfig) == 'table' then + config = tablex.merge(config, runConfig, true) return config else @@ -20,7 +23,7 @@ return function() end if configFile and type(configFile.default) == 'table' then - return tablex.merge(config, configFile.default, true) + config = tablex.merge(config, configFile.default, true) end return config diff --git a/spec/modules/configuration_loader_spec.lua b/spec/modules/configuration_loader_spec.lua index 5aabf60c..e93cc7ef 100644 --- a/spec/modules/configuration_loader_spec.lua +++ b/spec/modules/configuration_loader_spec.lua @@ -31,9 +31,10 @@ describe('Config Loader', function() end) it('returns a valid config with specified config', function() - local config, err = configLoader(testConfig, cliArgs, 'windows') + cliArgs.run = 'windows' + local config, err = configLoader(testConfig, cliArgs) - assert.are.same(testConfig.windows, config) + assert.are.same(testConfig.windows.output, config.output) assert.are.equal(nil, err) end) @@ -43,7 +44,8 @@ describe('Config Loader', function() end) it('returns an error with an invalid run', function() - local config, err = configLoader(testConfig, cliArgs, 'run') + cliArgs.run = 'invalid' + local config, err = configLoader(testConfig, cliArgs) assert.are_not.equal(nil, err) end) end) From 75c19a8f50ac9761c9c7941cc15a3a00e9649dae Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Thu, 14 Aug 2014 20:26:24 -0700 Subject: [PATCH 010/293] Clean up globals --- bin/busted | 2 +- busted/modules/files/lua.lua | 2 +- busted/outputHandlers/TAP.lua | 1 - busted/outputHandlers/junit.lua | 4 ---- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/bin/busted b/bin/busted index 7174427c..c3847735 100755 --- a/bin/busted +++ b/bin/busted @@ -140,7 +140,7 @@ local outputHandlerOptions = { deferPrint = cliArgs['defer-print'] } -outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted) +local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted) outputHandler:subscribe(outputHandlerOptions) if cliArgs.s then diff --git a/busted/modules/files/lua.lua b/busted/modules/files/lua.lua index 5e0afda1..95437807 100644 --- a/busted/modules/files/lua.lua +++ b/busted/modules/files/lua.lua @@ -16,7 +16,7 @@ end ret.load = function(busted, filename) - local file + local file, err local success, err = pcall(function() file, err = loadfile(filename) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index 83ff8c87..03ef4d63 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -11,7 +11,6 @@ return function(options, busted) while parent and (parent.name or parent.descriptor) and parent.descriptor ~= 'file' do - current_context = context.parent table.insert(names, 1, parent.name or parent.descriptor) parent = busted.context.parent(parent) end diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index ba92acb0..ce64a20d 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -44,10 +44,6 @@ return function(options, busted) end handler.error = function(element, parent, message, trace) - if status == 'failure' then - node.attr.errors = node.attr.errors + 1 - end - node:addtag('failure', { message = message }):text(trace.traceback):up() From 7d1828ea8d5b1417bb95f5b6679f572d68956774 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Thu, 14 Aug 2014 20:28:06 -0700 Subject: [PATCH 011/293] Fix junit -- @benbarbour --- busted/outputHandlers/junit.lua | 75 ++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index ce64a20d..4f125992 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -1,61 +1,70 @@ local xml = require 'pl.xml' -local hostname = assert(io.popen('uname -n')):read('*l') +local socket = require("socket") +local string = require("string") return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) - local node + local xml_doc + local suiteStartTime, suiteEndTime - handler.testEnd = function(element, parent, status) - node.attr.tests = node.attr.tests + 1 - - node:addtag('testcase', { - classname = element.trace.short_src .. ':' .. element.trace.currentline, - name = element.name - }) - - if status == 'failure' then - node.attr.failures = node.attr.failures + 1 - end - - return nil, true - end - - handler.suiteStart = function(name, parent) - node = xml.new('testsuite', { + handler.suiteStart = function() + suiteStartTime = socket.gettime() + xml_doc = xml.new('testsuite', { tests = 0, errors = 0, failures = 0, skip = 0, - header = 'Busted Suite', - hostname = hostname, - timestamp = os.time() }) return nil, true end - handler.suiteEnd = function(name, parent) - local ms = handler.getDuration() - node.attr.time = ms + local function now() + return string.format("%.2f", (socket.gettime() - suiteStartTime)) + end - print(xml.tostring(node, '', '\t')) + handler.suiteEnd = function() + xml_doc.attr.time = now() + + print(xml.tostring(xml_doc, '', '\t', nil, false)) return nil, true end - handler.error = function(element, parent, message, trace) - node:addtag('failure', { - message = message - }):text(trace.traceback):up() + handler.testEnd = function(element, parent, status) + xml_doc.attr.tests = xml_doc.attr.tests + 1 + + local testcase_node = xml.new('testcase', { + classname = element.trace.short_src .. ':' .. element.trace.currentline, + name = handler.getFullName(element), + time = now() + }) + xml_doc:add_direct_child(testcase_node) + + if status == 'failure' then + xml_doc.attr.failures = xml_doc.attr.failures + 1 + testcase_node:addtag('failure') + testcase_node:text(element.trace.traceback) + testcase_node:up() + end + + return nil, true + end + + handler.errorFile = function() + if status == 'failure' then + xml_doc.attr.errors = xml_doc.attr.errors + 1 + end + + xml_doc:addtag('failure', {}):text(trace.traceback):up() return nil, true end - busted.subscribe({ 'test', 'end' }, handler.testEnd) busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) - busted.subscribe({ 'error', 'file' }, handler.error) - busted.subscribe({ 'error', 'describe' }, handler.error) + busted.subscribe({ 'test', 'end' }, handler.testEnd) + busted.subscribe({ 'error', 'file' }, handler.errorFile) return handler end From 52f9e58b8f0d14d8173a1a8bfb82b64da7d43464 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Thu, 14 Aug 2014 20:52:15 -0700 Subject: [PATCH 012/293] Really suppress pending --- busted/init.lua | 30 +++++++++++++++---------- busted/outputHandlers/base.lua | 14 ++++++++++-- busted/outputHandlers/junit.lua | 2 +- busted/outputHandlers/plainTerminal.lua | 2 +- busted/outputHandlers/utfTerminal.lua | 2 +- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index c1231dc3..229039a1 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -72,30 +72,36 @@ return function(busted) busted.publish({ 'describe', 'end' }, describe, parent) end - local it = function(it) + local it = function(element) local finally - if not it.env then it.env = {} end + if not element.env then element.env = {} end - it.env.finally = function(fn) + element.env.finally = function(fn) finally = fn end - local parent = busted.context.parent(it) + local parent = busted.context.parent(element) execAll('before_each', parent, true) - busted.publish({ 'test', 'start' }, it, parent) - local res = busted.safe('it', it.run, it) - if not it.env.done then - busted.publish({ 'test', 'end' }, it, parent, res and 'success' or 'failure') - if finally then busted.safe('finally', finally, it) end + + busted.publish({ 'test', 'start' }, element, parent) + busted.publish({ 'test', 'foo' }, element, parent) + + local res = busted.safe('element', element.run, element) + if not element.env.done then + local trace = busted.getTrace(element, 3) + busted.publish({ 'test', 'end' }, element, parent, res and 'success' or 'failure', trace) + if finally then busted.safe('finally', finally, element) end dexecAll('after_each', parent, true) end end - local pending = function(pending) - local trace = busted.getTrace(pending, 3) - busted.publish({ 'test', 'end' }, pending, busted.context.parent(pending), 'pending', trace) + local pending = function(element) + local parent = busted.context.parent(pending) + local trace = busted.getTrace(element, 3) + busted.publish({ 'test', 'start' }, element, parent) + busted.publish({ 'test', 'end' }, element, parent, 'pending', trace) end busted.register('file', file) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 2b4baf58..f2d6f4e6 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -11,8 +11,13 @@ return function(busted) inProgress = {} } + handler.cancelOnPending = function(element) + return not (element.descriptor == 'pending' and handler.options.suppressPending) + end + handler.subscribe = function(handler, options) require('busted.languages.en') + handler.options = options if options.language ~= 'en' then require('busted.languages.' .. options.language) @@ -20,8 +25,8 @@ return function(busted) busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd) - busted.subscribe({ 'test', 'start' }, handler.baseTestStart) - busted.subscribe({ 'test', 'end' }, handler.baseTestEnd) + busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'error' }, handler.baseError) end @@ -72,11 +77,16 @@ return function(busted) end handler.baseTestStart = function(element, parent) + if element.descriptor == 'pending' and handler.options.suppressPending then + return nil, false + end + handler.inProgress[tostring(element)] = {} return nil, true end handler.baseTestEnd = function(element, parent, status, debug) + local insertTable local id = tostring(element) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 4f125992..c11df0db 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -63,7 +63,7 @@ return function(options, busted) busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) - busted.subscribe({ 'test', 'end' }, handler.testEnd) + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'error', 'file' }, handler.errorFile) return handler diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index c7024a97..00eeaf3d 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -142,7 +142,7 @@ return function(options, busted) return nil, true end - busted.subscribe({ 'test', 'end' }, handler.testEnd) + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) busted.subscribe({ 'error', 'describe' }, handler.error) diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 792f02d6..5af344ef 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -143,7 +143,7 @@ return function(options, busted) return nil, true end - busted.subscribe({ 'test', 'end' }, handler.testEnd) + local s = busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) busted.subscribe({ 'error', 'describe' }, handler.error) From f5b2c4a510294ad624543e4f4de02c6c8b2f2f70 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Thu, 14 Aug 2014 20:55:14 -0700 Subject: [PATCH 013/293] v2 rc2 --- busted-2.0.rc1-0.rockspec => busted-2.0.rc2-0.rockspec | 6 +++--- busted/core.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename busted-2.0.rc1-0.rockspec => busted-2.0.rc2-0.rockspec (96%) diff --git a/busted-2.0.rc1-0.rockspec b/busted-2.0.rc2-0.rockspec similarity index 96% rename from busted-2.0.rc1-0.rockspec rename to busted-2.0.rc2-0.rockspec index c64c3981..426ff042 100644 --- a/busted-2.0.rc1-0.rockspec +++ b/busted-2.0.rc2-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc1-0' +version = '2.0.rc2-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc1.tar.gz', - dir = 'busted-2.0.rc1' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc2.tar.gz', + dir = 'busted-2.0.rc2' } description = { summary = 'Elegant Lua unit testing.', diff --git a/busted/core.lua b/busted/core.lua index f574ec90..510e937a 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -2,7 +2,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc1-0' + busted.version = '2.0.rc2-0' local root = require 'busted.context'() busted.context = root.ref() From e58462bd12db6e5d60a5f21e222f9351e1eec9aa Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Wed, 27 Aug 2014 13:19:13 -0700 Subject: [PATCH 014/293] rc3 --- busted-2.0.rc2-0.rockspec => busted-2.0.rc3-0.rockspec | 8 ++++---- busted/core.lua | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename busted-2.0.rc2-0.rockspec => busted-2.0.rc3-0.rockspec (95%) diff --git a/busted-2.0.rc2-0.rockspec b/busted-2.0.rc3-0.rockspec similarity index 95% rename from busted-2.0.rc2-0.rockspec rename to busted-2.0.rc3-0.rockspec index 426ff042..2bc7f332 100644 --- a/busted-2.0.rc2-0.rockspec +++ b/busted-2.0.rc3-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc2-0' +version = '2.0.rc3-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc2.tar.gz', - dir = 'busted-2.0.rc2' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc3.tar.gz', + dir = 'busted-2.0.rc3' } description = { summary = 'Elegant Lua unit testing.', @@ -23,7 +23,7 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.2-1', - 'luassert >= 1.7.0-0', + 'luassert >= 1.7.1-0', 'ansicolors >= 1.0-1', 'penlight >= 1.0.0-1', 'mediator_lua >= 1.1-3', diff --git a/busted/core.lua b/busted/core.lua index 510e937a..6cc36494 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -2,7 +2,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc2-0' + busted.version = '2.0.rc3-0' local root = require 'busted.context'() busted.context = root.ref() From 1afad72ac45fa5377d06a5a188f94a73b2f177b9 Mon Sep 17 00:00:00 2001 From: Florian Walch Date: Sat, 30 Aug 2014 19:27:24 +0200 Subject: [PATCH 015/293] Output handlers: Concatenate traceback only if it is not nil. --- busted/outputHandlers/plainTerminal.lua | 2 +- busted/outputHandlers/utfTerminal.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 00eeaf3d..60fe734d 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -44,7 +44,7 @@ return function(options, busted) end end - if options.verbose then + if options.verbose and failure.trace.traceback then string = string .. '\n' .. failure.trace.traceback end diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 5af344ef..dcd36c08 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -45,7 +45,7 @@ return function(options, busted) end end - if options.verbose then + if options.verbose and failure.trace.traceback then string = string .. '\n' .. failure.trace.traceback end From 66468fbad727c1a734a9f8e3fbc62fb823f5ac0c Mon Sep 17 00:00:00 2001 From: Ryan Hartlage Date: Mon, 29 Sep 2014 14:04:58 -0400 Subject: [PATCH 016/293] Correctly use loaded config file --- bin/busted | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/busted b/bin/busted index c3847735..c67e57b9 100755 --- a/bin/busted +++ b/bin/busted @@ -71,6 +71,8 @@ if bustedConfigFile then if err then print(err) + else + cliArgs = config end end From 9ceee593d9c676aa93a3c206d547ddf5f11f28e5 Mon Sep 17 00:00:00 2001 From: Steven Chan Date: Wed, 3 Dec 2014 13:09:49 -0800 Subject: [PATCH 017/293] Fix issue #291 TAP output type is broken in 2.0rc3 The success and failure format strings were bypassed in commit 88f7850. Now, if the following two tests are run with TAP output, we will get the expected ok/not ok formats. $ bin/busted -o TAP spec/cl_spec.lua 1..1 ok 1 - Tests the busted command-line options $ bin/busted -o TAP spec/cl_two_failures.lua 1..2 not ok 1 - Runs 2 failing tests is failing test 2 (details omitted) not ok 2 - Runs 2 failing tests is failing test 1 (details omitted) --- busted/outputHandlers/TAP.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index 03ef4d63..b1fd18d6 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -28,7 +28,7 @@ return function(options, busted) for i,t in pairs(handler.successes) do counter = counter + 1 - print(counter .. ' ' .. handler.format(t).name) + print( success:format( counter, handler.format(t).name )) end for i,t in pairs(handler.failures) do @@ -41,7 +41,7 @@ return function(options, busted) message = pretty.write(message) end - print(counter .. ' ' .. handler.format(t).name) + print( failure:format( counter, handler.format(t).name )) print('# ' .. t.trace.short_src .. ' @ ' .. t.trace.currentline) print('# Failure message: ' .. message:gsub('\n', '\n# ' )) end From 9db558e35cc0ff9ee624d049b0d49588544e5fa1 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 26 Nov 2014 21:51:37 -0800 Subject: [PATCH 018/293] Remove unnecessary publish test foo --- busted/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/busted/init.lua b/busted/init.lua index 229039a1..3b184690 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -86,7 +86,6 @@ return function(busted) execAll('before_each', parent, true) busted.publish({ 'test', 'start' }, element, parent) - busted.publish({ 'test', 'foo' }, element, parent) local res = busted.safe('element', element.run, element) if not element.env.done then From 9e18d1943b6b2f4341e7d82c032c0d3c8944e7e3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 24 Nov 2014 23:36:44 -0800 Subject: [PATCH 019/293] Fix after_each execution order Execution order of after_each was not quite right. The order should be from the inner most block outward. However, the execution was running the inner most block first followed by the outter most block going inward. --- busted/init.lua | 2 +- spec/execution_order_sync_spec.lua | 33 +++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 3b184690..1e27f2a9 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -35,7 +35,7 @@ return function(busted) end end - if propagate and parent then execAll(descriptor, parent, propagate) end + if propagate and parent then dexecAll(descriptor, parent, propagate) end end local file = function(file) diff --git a/spec/execution_order_sync_spec.lua b/spec/execution_order_sync_spec.lua index c062be7f..ecb475e4 100644 --- a/spec/execution_order_sync_spec.lua +++ b/spec/execution_order_sync_spec.lua @@ -35,15 +35,38 @@ describe('before_each after_each egg test', function() assert.equal(egg,'SbB1AabB') egg = egg..'2' end) + + describe('jkl', function() + setup(function() + egg = egg..'s' + end) + + teardown(function() + egg = egg..'t' + end) + + before_each(function() + egg = egg..'E' + end) + + after_each(function() + egg = egg..'F' + end) + + it('3', function() + assert.equal(egg,'SbB1AabB2AasbBE') + egg = egg..'3' + end) + end) end) - it('3', function() - assert.equal(egg,'SbB1AabB2Aab') - egg = egg..'3' + it('4', function() + assert.equal(egg,'SbB1AabB2AasbBE3FAatb') + egg = egg..'4' end) end) -it('4', function() - assert.equal(egg,'SbB1AabB2Aab3aT') +it('5', function() + assert.equal(egg,'SbB1AabB2AasbBE3FAatb4aT') end) From e5b51d6e9f8ffa634f6faa4a8e73cd2698c45ba7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 25 Nov 2014 00:42:19 -0800 Subject: [PATCH 020/293] Fix traceback issue #286 The base output handler was not saving the trace info when it was notified that an error/failure occurred. The error/failure handler needs to save the trace information, otherwise the trace information of the test call site will be used. Furthermore, we do not need to pass in trace information for test end messages, since the trace information is already present in the context element at creation. The output handler formatter just needs to prioritize the passed in debug information over the context element's trace information since the passed in debug information will provide more precise location information. --- busted/init.lua | 6 ++---- busted/outputHandlers/base.lua | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 1e27f2a9..5edf23cf 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -89,8 +89,7 @@ return function(busted) local res = busted.safe('element', element.run, element) if not element.env.done then - local trace = busted.getTrace(element, 3) - busted.publish({ 'test', 'end' }, element, parent, res and 'success' or 'failure', trace) + busted.publish({ 'test', 'end' }, element, parent, res and 'success' or 'failure') if finally then busted.safe('finally', finally, element) end dexecAll('after_each', parent, true) end @@ -98,9 +97,8 @@ return function(busted) local pending = function(element) local parent = busted.context.parent(pending) - local trace = busted.getTrace(element, 3) busted.publish({ 'test', 'start' }, element, parent) - busted.publish({ 'test', 'end' }, element, parent, 'pending', trace) + busted.publish({ 'test', 'end' }, element, parent, 'pending') end busted.register('file', file) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index f2d6f4e6..56903aa6 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -48,7 +48,7 @@ return function(busted) handler.format = function(element, parent, message, debug, isError) local formatted = { - trace = element.trace or debug, + trace = debug or element.trace, name = handler.getFullName(element), message = message, isError = isError @@ -116,7 +116,9 @@ return function(busted) handler.baseError = function(element, parent, message, debug) if element.descriptor == 'it' then - handler.inProgress[tostring(element)].message = message + local id = tostring(element) + handler.inProgress[id].message = message + handler.inProgress[id].trace = debug else handler.errorsCount = handler.errorsCount + 1 table.insert(handler.errors, handler.format(element, parent, message, debug, true)) From 3a7b9237ccea6292389d21248ed983d7eeec6134 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 25 Nov 2014 01:28:05 -0800 Subject: [PATCH 021/293] Distinguish between test errors and test failures A test error occurs when an error is thrown or an assert fails outside of the test. While test failures only occur when an assert fails inside a test. Call setfenv on 'assert' to replace 'error' with 'fail', such that 'fail' throws a special failure table instead of a string. Hence, assertion failures will throw a failure table and are distinct from errors. Additionally, the failure table contains the same error string that would have been thrown with 'error'. --- busted/compatibility.lua | 13 +++ busted/core.lua | 50 +++++++++- busted/init.lua | 11 ++- busted/outputHandlers/base.lua | 8 +- busted/outputHandlers/plainTerminal.lua | 6 +- busted/outputHandlers/utfTerminal.lua | 8 +- spec/cl_errors.lua | 14 +++ spec/cl_spec.lua | 123 ++++++++++++++++++++++++ spec/cl_two_failures.lua | 8 +- 9 files changed, 227 insertions(+), 14 deletions(-) create mode 100644 spec/cl_errors.lua diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 30279b4a..12d5bd16 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -1,4 +1,17 @@ return { + getfenv = getfenv or function(f) + f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func) + local name, value + local up = 0 + + repeat + up = up + 1 + name, value = debug.getupvalue(f, up) + until name == '_ENV' or name == nil + + return (name and value or _G) + end, + setfenv = setfenv or function(f, t) f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func) local name diff --git a/busted/core.lua b/busted/core.lua index 6cc36494..18483d47 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -1,3 +1,24 @@ +local metatype = function(obj) + local otype = type(obj) + if otype == 'table' then + local mt = getmetatable(obj) + if mt and mt.__type then + return mt.__type + end + end + return otype +end + +local failureMt = { + __index = {}, + __tostring = function(e) return e.message end, + __type = 'failure' +} + +local getfenv = require 'busted.compatibility'.getfenv +local setfenv = require 'busted.compatibility'.setfenv +local throw = error + return function() local mediator = require 'mediator'() @@ -16,6 +37,12 @@ return function() level = level or 3 local info = debug.getinfo(level, 'Sl') + while info.what == 'C' or info.short_src:match('luassert[/\\].*%.lua$') or + info.short_src:match('busted[/\\].*%.lua$') do + level = level + 1 + info = debug.getinfo(level, 'Sl') + end + info.traceback = debug.traceback('', level) info.message = msg @@ -64,6 +91,21 @@ return function() return parent end + function busted.fail(msg, level) + local _, emsg = pcall(error, msg, level+2) + local e = { message = emsg } + setmetatable(e, failureMt) + throw(e, level+1) + end + + function busted.replaceErrorWithFail(callable) + local env = {} + local f = getmetatable(callable).__call or callable + setmetatable(env, { __index = getfenv(f) }) + env.error = busted.fail + setfenv(f, env) + end + function busted.safe(descriptor, run, element, setenv) if setenv and (type(run) == 'function' or getmetatable(run).__call) then -- prioritize __call if it exists, like in files @@ -72,15 +114,19 @@ return function() busted.context.push(element) local trace, message + local status = 'success' local ret = { xpcall(run, function(msg) - message = busted.rewriteMessage(element, msg) + local errType = metatype(msg) + status = (errType == 'string' and 'error' or errType) + message = busted.rewriteMessage(element, tostring(msg)) trace = busted.getTrace(element, 3, msg) end) } if not ret[1] then - busted.publish({ 'error', descriptor }, element, busted.context.parent(element), message, trace) + busted.publish({ status, descriptor }, element, busted.context.parent(element), message, trace) end + ret[1] = status busted.context.pop() return unpack(ret) diff --git a/busted/init.lua b/busted/init.lua index 5edf23cf..ff435a21 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -41,7 +41,7 @@ return function(busted) local file = function(file) busted.publish({ 'file', 'start' }, file.name) - if busted.safe('file', file.run, file, true) then + if busted.safe('file', file.run, file, true) == 'success' then busted.execute(file) end @@ -60,7 +60,7 @@ return function(busted) randomize = true end - if busted.safe('describe', describe.run, describe) then + if busted.safe('describe', describe.run, describe) == 'success' then if randomize then shuffle(busted.context.children(describe)) end @@ -87,9 +87,9 @@ return function(busted) busted.publish({ 'test', 'start' }, element, parent) - local res = busted.safe('element', element.run, element) + local status = busted.safe('element', element.run, element) if not element.env.done then - busted.publish({ 'test', 'end' }, element, parent, res and 'success' or 'failure') + busted.publish({ 'test', 'end' }, element, parent, status) if finally then busted.safe('finally', finally, element) end dexecAll('after_each', parent, true) end @@ -119,5 +119,8 @@ return function(busted) mock = require 'luassert.mock' stub = require 'luassert.stub' + busted.replaceErrorWithFail(assert) + busted.replaceErrorWithFail(assert.True) + return busted end diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 56903aa6..3452ea09 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -27,6 +27,7 @@ return function(busted) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd) busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'failure' }, handler.baseError) busted.subscribe({ 'error' }, handler.baseError) end @@ -87,6 +88,7 @@ return function(busted) handler.baseTestEnd = function(element, parent, status, debug) + local isError local insertTable local id = tostring(element) @@ -99,9 +101,13 @@ return function(busted) elseif status == 'failure' then insertTable = handler.failures handler.failuresCount = handler.failuresCount + 1 + elseif status == 'error' then + insertTable = handler.errors + handler.errorsCount = handler.errorsCount + 1 + isError = true end - insertTable[id] = handler.format(element, parent, nil, debug) + insertTable[id] = handler.format(element, parent, nil, debug, isError) if handler.inProgress[id] then for k, v in pairs(handler.inProgress[id]) do diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 60fe734d..26b0e8e4 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -29,6 +29,8 @@ return function(options, busted) if failure.message then string = string .. ' → ' .. failure.message .. '\n' end + string = string .. + handler.getFullName(failure) else string = string .. failure.trace.short_src .. ' @ ' .. @@ -44,7 +46,7 @@ return function(options, busted) end end - if options.verbose and failure.trace.traceback then + if options.verbose and failure.trace and failure.trace.traceback then string = string .. '\n' .. failure.trace.traceback end @@ -104,6 +106,8 @@ return function(options, busted) string = pendingDot elseif status == 'failure' then string = failureDot + elseif status == 'error' then + string = errorDot end io.write(string) diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index dcd36c08..5b76ca6a 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -30,6 +30,8 @@ return function(options, busted) if failure.message then string = string .. ' → ' .. ansicolors('%{cyan}' .. failure.message) .. '\n' end + string = string .. + ansicolors('%{bright}' .. handler.getFullName(failure)) else string = string .. ansicolors('%{cyan}' .. failure.trace.short_src) .. ' @ ' .. @@ -45,7 +47,7 @@ return function(options, busted) end end - if options.verbose and failure.trace.traceback then + if options.verbose and failure.trace and failure.trace.traceback then string = string .. '\n' .. failure.trace.traceback end @@ -105,6 +107,8 @@ return function(options, busted) string = pendingDot elseif status == 'failure' then string = failureDot + elseif status == 'error' then + string = errorDot end io.write(string) @@ -143,7 +147,7 @@ return function(options, busted) return nil, true end - local s = busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) busted.subscribe({ 'error', 'describe' }, handler.error) diff --git a/spec/cl_errors.lua b/spec/cl_errors.lua new file mode 100644 index 00000000..29d4a360 --- /dev/null +++ b/spec/cl_errors.lua @@ -0,0 +1,14 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Tests the busted error detection through the commandline', function() + + it('is a test that throws an error #testerr', function() + error('force an error') + end) + + it('is a test with a Lua error #luaerr', function() + local foo + foo.bar = nil + end) +end) + diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 565f4238..76619d11 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -36,6 +36,13 @@ local execute = function(cmd) return not not success, modexit(exitcode) end +local run = function(cmd) + local p = io.popen(cmd, 'r') + local out = p:read('*a') + p:close() + return out +end + it('Tests the busted command-line options', function() @@ -178,5 +185,121 @@ describe('Tests failing tests through the commandline', function() assert.is_equal(8, exitcode) error_end() end) + + it('tests failing support functions as errors', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_failing_support.lua$') + local _, numErrors = result:gsub('Error → .-\n','') + assert.is_equal(8, numErrors) + error_end() + end) +end) + +describe('Tests distinguish between errors and failures', function() + it('by detecting errors as test errors', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') + local errmsg = result:match('(Error → .-)\n') + assert.is_truthy(errmsg) + error_end() + end) + + it('by detecting assert failures as test failures', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_two_failures.lua$') + local failmsg = result:match('(Failure → .-)\n') + assert.is_truthy(failmsg) + error_end() + end) + + it('by detecting Lua runtime errors as test errors', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=luaerr') + local failmsg = result:match('(Error → .-)\n') + assert.is_truthy(failmsg) + error_end() + end) +end) + +describe('Tests stack trackback', function() + it('when throwing an error', function() + error_start() + local result = run('bin/busted --verbose --pattern=cl_errors.lua$ --tags=testerr') + local errmsg = result:match('(stack traceback:.*)\n') + local expected = [[stack traceback: + ./spec/cl_errors.lua:6: in function <./spec/cl_errors.lua:5> +]] + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when assertion fails', function() + error_start() + local result = run('bin/busted --verbose --pattern=cl_two_failures.lua$ --tags=err1') + local errmsg = result:match('(stack traceback:.*)\n') + local expected = [[stack traceback: + ./spec/cl_two_failures.lua:6: in function <./spec/cl_two_failures.lua:5> +]] + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when Lua runtime error', function() + error_start() + local result = run('bin/busted --verbose --pattern=cl_errors.lua$ --tags=luaerr') + local errmsg = result:match('(stack traceback:.*)\n') + local expected = [[stack traceback: + ./spec/cl_errors.lua:11: in function <./spec/cl_errors.lua:9> +]] + assert.is_equal(expected, errmsg) + error_end() + end) +end) + +describe('Tests error messages through the command line', function() + it('when throwing errors in a test', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') + local errmsg = result:match('(Error → .-)\n') + local expected = "Error → ./spec/cl_errors.lua:6: force an error" + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when running a non-compiling testfile', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_compile_fail.lua$') + local errmsg = result:match('(Error → .-)\n') + local expected = "Error → ./spec/cl_compile_fail.lua:3: '=' expected near 'here'" + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when a testfile throws errors', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_execute_fail.lua$') + local errmsg = result:match('(Error → .-)\n') + local expected = 'Error → ./spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when output library not found', function() + error_start() + local result = run('bin/busted --pattern=cl_two_failures.lua$ --output=not_found_here') + local errmsg = result:match('(.-)\n') + local expected = 'Cannot load output library: not_found_here' + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when no test files matching Lua pattern', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') + local errmsg = result:match('(.-)\n') + local expected = 'No test files found matching Lua pattern: this_filename_does_simply_not_exist$' + assert.is_equal(expected, errmsg) + error_end() + end) end) --]] diff --git a/spec/cl_two_failures.lua b/spec/cl_two_failures.lua index 500347c8..083ec844 100644 --- a/spec/cl_two_failures.lua +++ b/spec/cl_two_failures.lua @@ -2,12 +2,12 @@ describe('Runs 2 failing tests', function() - it('is failing test 1', function() - error('error on test 1') + it('is failing test 1 #err1', function() + assert(false, 'failed on test 1') end) - it('is failing test 2', function() - error('error on test 2') + it('is failing test 2 #err2', function() + assert(false, 'failed on test 2') end) end) From 087be17eb57139c7dde8da1be1ddf218e50c2a3f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 25 Nov 2014 00:19:12 -0800 Subject: [PATCH 022/293] Enable/Fix failing tests in cl_spec.lua Tests in cl_spec.lua were not being executed because they were nested inside an 'it' block. Tests need to be in a 'describe' block in order to execute, otherwise they are silently disabled. Nesting an 'it' block inside another 'it' block should probably be an error. After enabling the tests, many of the tests were failing. Tags were not being filtered correctly. Instead of running tests with one or more tags listed in the --tags option, tests were being excluded if any of the listed tags were not present. Need to incorporate pull request #293 in order to fix the compile fail test. This also addresses issue #273. According to the tests, the return code for busted should be the number of errors/failures. However, the return code needs to saturate at 255 since it can only occupy 8-bits. --- bin/busted | 64 ++++++++++++++---------- busted/modules/files/lua.lua | 16 ++---- busted/modules/output_handler_loader.lua | 17 +++++-- busted/modules/test_file_loader.lua | 2 + spec/cl_spec.lua | 18 ++----- 5 files changed, 59 insertions(+), 58 deletions(-) diff --git a/bin/busted b/bin/busted index c67e57b9..aa4ee2bb 100755 --- a/bin/busted +++ b/bin/busted @@ -134,6 +134,27 @@ for _, excluded in pairs(excludeTags) do end end +-- watch for test errors +local failures = 0 +local errors = 0 + +busted.subscribe({ 'error' }, function(element, parent, status) + if element.descriptor == 'output' then + print('Cannot load output library: ' .. element.name) + end + errors = errors + 1 + return nil, true +end) + +busted.subscribe({ 'failure' }, function(element, parent, status) + if element.descriptor == 'it' then + failures = failures + 1 + else + errors = errors + 1 + end + return nil, true +end) + -- Set up output handler to listen to events local outputHandlerOptions = { verbose = cliArgs.verbose, @@ -142,32 +163,32 @@ local outputHandlerOptions = { deferPrint = cliArgs['defer-print'] } -local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted) +local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted, defaultOutput) outputHandler:subscribe(outputHandlerOptions) if cliArgs.s then require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) end -local checkTag = function(name, tag, modifier) +local hasTag = function(name, tag) local found = name:find('#' .. tag) - return (modifier == (found ~= nil)) + return (found ~= nil) end local checkTags = function(name) - for i, tag in pairs(tags) do - if not checkTag(name, tag, true) then + for i, tag in pairs(excludeTags) do + if hasTag(name, tag) then return nil, false end end - for i, tag in pairs(excludeTags) do - if not checkTag(name, tag, false) then - return nil, false + for i, tag in pairs(tags) do + if hasTag(name, tag) then + return nil, true end end - return nil, true + return nil, (#tags == 0) end if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then @@ -177,23 +198,11 @@ if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then end local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) -testFileLoader(rootFile, pattern) - --- watch for test errors -local failures = 0 -local errors = 0 - -busted.subscribe({ 'error' }, function(...) +local fileList = testFileLoader(rootFile, pattern) +if #fileList == 0 then + print('No test files found matching Lua pattern: ' .. pattern) errors = errors + 1 - return nil, true -end) - -busted.subscribe({ 'test', 'end' }, function(element, parent, status) - if status == 'failure' then - failures = failures + 1 - end - return nil, true -end) +end busted.publish({ 'suite', 'start' }) busted.execute() @@ -201,6 +210,9 @@ busted.publish({ 'suite', 'end' }) local exit = 0 if failures > 0 or errors > 0 then - exit = 1 + exit = failures + errors + if exit > 255 then + exit = 255 + end end os.exit(exit) diff --git a/busted/modules/files/lua.lua b/busted/modules/files/lua.lua index 95437807..99846b11 100644 --- a/busted/modules/files/lua.lua +++ b/busted/modules/files/lua.lua @@ -16,20 +16,10 @@ end ret.load = function(busted, filename) - local file, err - - local success, err = pcall(function() - file, err = loadfile(filename) - - if not file then - busted.publish({ 'error', 'file' }, filename, nil, nil, err) - end - end) - - if not success then - busted.publish({ 'error', 'file' }, filename, nil, nil, err) + local file, err = loadfile(filename) + if not file then + busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) end - return file, getTrace end diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index df9a3de4..fcbceb43 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -1,13 +1,20 @@ local path = require 'pl.path' return function() - local loadOutputHandler = function(output, opath, options, busted) + local loadOutputHandler = function(output, opath, options, busted, defaultOutput) local handler - if output:match('.lua$') or output:match('.moon$') then - handler = loadfile(path.normpath(opath))() - else - handler = require('busted.outputHandlers.'..output) + local success, err = pcall(function() + if output:match('.lua$') or output:match('.moon$') then + handler = loadfile(path.normpath(opath))() + else + handler = require('busted.outputHandlers.'..output) + end + end) + + if not success then + busted.publish({ 'error', 'output' }, { descriptor = 'output', name = output }, nil, err, {}) + handler = require('busted.outputHandlers.'..defaultOutput) end return handler(options, busted) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index cb46f5a4..5f2159b4 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -62,6 +62,8 @@ return function(busted, loaders) busted.executors.file(fileName, file) end end + + return fileList end return loadTestFiles, loadTestFile, getTestFiles diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 76619d11..80944ca4 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -44,7 +44,7 @@ local run = function(cmd) end -it('Tests the busted command-line options', function() +describe('Tests the busted command-line options', function() setup(function() require('pl') @@ -121,8 +121,8 @@ it('Tests the busted command-line options', function() it('tests running with --help specified', function() local success, exitcode success, exitcode = execute('bin/busted --help') - assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_false(success) + assert.is_equal(1, exitcode) end) it('tests running a non-compiling testfile', function() @@ -167,20 +167,11 @@ it('Tests the busted command-line options', function() end) ---[[ --TODO: uncomment this failing test and fix it describe('Tests failing tests through the commandline', function() - local old_ditch - before_each(function() - old_ditch, ditch = ditch, '' -- dump this test output only - end) - after_each(function() - ditch = old_ditch - end) - it('tests failing setup/before_each/after_each/teardown functions', function() local success, exitcode error_start() - success, exitcode = execute('busted --pattern=cl_failing_support.lua$') + success, exitcode = execute('bin/busted --pattern=cl_failing_support.lua$') assert.is_false(success) assert.is_equal(8, exitcode) error_end() @@ -302,4 +293,3 @@ describe('Tests error messages through the command line', function() error_end() end) end) ---]] From c2ffccf115dc94bcc96033553d449789d38ae30e Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 25 Nov 2014 01:39:34 -0800 Subject: [PATCH 023/293] Support 'pending' inside an 'it' block When 'pending' is called from an 'it' block, the rest of the test should be skipped and the test should be flagged as pending. This can be acheived by throwing a 'pending' table when 'pending' is called from an 'it' block, then publishing a 'pending' message when the 'pending' table is caught. This causes the remainder of the test to be skipped and the output handler to be notified that the current test is 'pending'. Also, make sure the --suppress-pending option is honored. --- busted/core.lua | 12 +++++++++ busted/init.lua | 3 +++ busted/outputHandlers/base.lua | 19 +++++++++----- busted/outputHandlers/plainTerminal.lua | 6 +++++ busted/outputHandlers/utfTerminal.lua | 6 +++++ spec/cl_pending.lua | 16 ++++++++++++ spec/cl_spec.lua | 33 +++++++++++++++++++++++++ 7 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 spec/cl_pending.lua diff --git a/busted/core.lua b/busted/core.lua index 18483d47..bbbe2f88 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -15,6 +15,12 @@ local failureMt = { __type = 'failure' } +local pendingMt = { + __index = {}, + __tostring = function(p) return p.message end, + __type = 'pending' +} + local getfenv = require 'busted.compatibility'.getfenv local setfenv = require 'busted.compatibility'.setfenv local throw = error @@ -98,6 +104,12 @@ return function() throw(e, level+1) end + function busted.pending(msg) + local p = { message = msg } + setmetatable(p, pendingMt) + throw(p) + end + function busted.replaceErrorWithFail(callable) local env = {} local f = getmetatable(callable).__call or callable diff --git a/busted/init.lua b/busted/init.lua index ff435a21..e52d0bcd 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -80,6 +80,9 @@ return function(busted) element.env.finally = function(fn) finally = fn end + element.env.pending = function(msg) + busted.pending(msg) + end local parent = busted.context.parent(element) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 3452ea09..08f2f9c7 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -11,8 +11,8 @@ return function(busted) inProgress = {} } - handler.cancelOnPending = function(element) - return not (element.descriptor == 'pending' and handler.options.suppressPending) + handler.cancelOnPending = function(element, parent, status) + return not ((element.descriptor == 'pending' or status == 'pending') and handler.options.suppressPending) end handler.subscribe = function(handler, options) @@ -27,6 +27,7 @@ return function(busted) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd) busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'pending' }, handler.basePending, { predicate = handler.cancelOnPending }) busted.subscribe({ 'failure' }, handler.baseError) busted.subscribe({ 'error' }, handler.baseError) end @@ -78,10 +79,6 @@ return function(busted) end handler.baseTestStart = function(element, parent) - if element.descriptor == 'pending' and handler.options.suppressPending then - return nil, false - end - handler.inProgress[tostring(element)] = {} return nil, true end @@ -120,6 +117,16 @@ return function(busted) return nil, true end + handler.basePending = function(element, parent, message, debug) + if element.descriptor == 'it' then + local id = tostring(element) + handler.inProgress[id].message = message + handler.inProgress[id].trace = debug + end + + return nil, true + end + handler.baseError = function(element, parent, message, debug) if element.descriptor == 'it' then local id = tostring(element) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 26b0e8e4..d9a9e659 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -17,6 +17,12 @@ return function(options, busted) pending.trace.currentline .. '\n' .. name + if type(pending.message) == 'string' then + string = string .. '\n' .. pending.message + elseif pending.message ~= nil then + string = string .. '\n' .. pretty.write(pending.message) + end + return string end diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 5b76ca6a..2f320257 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -18,6 +18,12 @@ return function(options, busted) ansicolors('%{cyan}' .. pending.trace.currentline) .. '\n' .. ansicolors('%{bright}' .. name) + if type(pending.message) == 'string' then + string = string .. '\n' .. pending.message + elseif pending.message ~= nil then + string = string .. '\n' .. pretty.write(pending.message) + end + return string end diff --git a/spec/cl_pending.lua b/spec/cl_pending.lua new file mode 100644 index 00000000..00fa7255 --- /dev/null +++ b/spec/cl_pending.lua @@ -0,0 +1,16 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Tests the busted pending functions through the commandline', function() + + it('is a test with a pending', function() + pending('finish this test later') + error('should never get here') + end) + + pending('is a pending inside a describe', function() + it('this test does not run', function() + error('this should not run') + end) + end) +end) + diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 80944ca4..946e806a 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -293,3 +293,36 @@ describe('Tests error messages through the command line', function() error_end() end) end) + +describe('Tests pending through the commandline', function() + it('skips tests inside pending scope', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --pattern=cl_pending.lua$') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) + + it('detects tests as pending', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_pending.lua$') + local line1 = result:match('.-\n') + local _, pendingDots = line1:gsub('%.', '') + local _, numPending = result:gsub('Pending → .-\n', '') + assert.is_equal(2, pendingDots) + assert.is_equal(2, numPending) + error_end() + end) + + it('--suppress-pending option is honored', function() + error_start() + local result = run('bin/busted --output=plainTerminal --suppress-pending --pattern=cl_pending.lua$') + local line1 = result:match('.-\n') + local _, pendingDots = line1:gsub('%.', '') + local _, numPending = result:gsub('Pending → .-\n', '') + assert.is_equal(0, pendingDots) + assert.is_equal(0, numPending) + error_end() + end) +end) From 26e53b5e299add12f20ef6ca87e8b40d51e20315 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 25 Nov 2014 21:06:30 -0800 Subject: [PATCH 024/293] Support spec/test aliases for it Add 'spec' and 'test' aliases for 'it' blocks. --- busted/init.lua | 3 +++ spec/core_spec.lua | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/busted/init.lua b/busted/init.lua index e52d0bcd..8e33c4a7 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -110,6 +110,9 @@ return function(busted) busted.register('context', describe) busted.register('it', it) + busted.register('spec', it) + busted.register('test', it) + busted.register('pending', pending) busted.register('setup') diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 1aff33d2..36db2a23 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -2,6 +2,8 @@ assert(type(describe) == 'function') assert(type(context) == 'function') assert(type(it) == 'function') +assert(type(spec) == 'function') +assert(type(test) == 'function') assert(type(before_each) == 'function') assert(type(after_each) == 'function') assert(type(spy) == 'table') @@ -245,3 +247,37 @@ describe('tests environment', function() assert.are.equal(notglobal, nil) end) end) + +describe('tests aliases', function() + local test_val = 0 + + context('runs context alias', function() + setup(function() + test_val = test_val + 1 + end) + + before_each(function() + test_val = test_val + 1 + end) + + after_each(function() + test_val = test_val + 1 + end) + + teardown(function() + test_val = test_val + 1 + end) + + spec('runs spec alias', function() + test_val = test_val + 1 + end) + + test('runs test alias', function() + test_val = test_val + 1 + end) + end) + + it('checks aliases were executed', function() + assert.is_equal(8, test_val) + end) +end) From d336b4b13b2b6b271e7ecd100f377b99ae268737 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 3 Dec 2014 21:10:41 -0800 Subject: [PATCH 025/293] Refactor descriptor executor registration Currently a debug trace is saved for registered descriptors that do not match 'file'. However, since the 'file' executor is only called by the test file loader directly, via busted.executors, before any files are run, it is sufficient to check that the current context does not have a parent instead of checking that the descriptor is not 'file'. --- busted/core.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index bbbe2f88..d5f64434 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -155,8 +155,9 @@ return function() local trace - if descriptor ~= 'file' then - trace = busted.getTrace(busted.context.get(), 3, name) + local ctx = busted.context.get() + if busted.context.parent(ctx) then + trace = busted.getTrace(ctx, 3, name) end busted.publish({ 'register', descriptor }, name, fn, trace) From df8019aa344c2817f5e6e7048d4a4bc32da0f15d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 1 Dec 2014 23:08:23 -0800 Subject: [PATCH 026/293] Remove file function from environment --- busted/core.lua | 4 +++- spec/cl_spec.lua | 1 - spec/core_spec.lua | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index d5f64434..913a10be 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -164,7 +164,9 @@ return function() end busted.executors[descriptor] = publisher - environment.set(descriptor, publisher) + if descriptor ~= 'file' then + environment.set(descriptor, publisher) + end busted.subscribe({ 'register', descriptor }, function(name, fn, trace) local ctx = busted.context.get() diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 946e806a..d756f53e 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -47,7 +47,6 @@ end describe('Tests the busted command-line options', function() setup(function() - require('pl') end) after_each(function() diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 36db2a23..7f94b1a7 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -1,4 +1,5 @@ --ensure environment is set up +assert(type(file) == 'nil') assert(type(describe) == 'function') assert(type(context) == 'function') assert(type(it) == 'function') From 1157b0b93619800501e6a76ca79442715f3f381d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 26 Nov 2014 01:10:00 -0800 Subject: [PATCH 027/293] Error when unsupported functions called from test Calling randomize/describe/it/setup/before_each/after_each/teardown functions from inside an 'it' block is not valid, so throw an error when any of these functions are called inside an 'it'. In addition, pending is not valid inside a 'finally' block. Ensure that the error string reflects the error level of the caller. --- busted/init.lua | 19 +++++++++++++------ spec/core_spec.lua | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 8e33c4a7..d74df82d 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -74,15 +74,21 @@ return function(busted) local it = function(element) local finally + local remove = function(descriptors) + for _, descriptor in ipairs(descriptors) do + element.env[descriptor] = function(...) + error("'"..descriptor.."' not supported inside an 'it' block", 2) + end + end + end if not element.env then element.env = {} end - element.env.finally = function(fn) - finally = fn - end - element.env.pending = function(msg) - busted.pending(msg) - end + remove({ 'randomize' }) + remove({ 'describe', 'context', 'it', 'spec', 'test' }) + remove({ 'setup', 'teardown', 'before_each', 'after_each' }) + element.env.finally = function(fn) finally = fn end + element.env.pending = function(msg) busted.pending(msg) end local parent = busted.context.parent(element) @@ -92,6 +98,7 @@ return function(busted) local status = busted.safe('element', element.run, element) if not element.env.done then + remove({ 'pending' }, element) busted.publish({ 'test', 'end' }, element, parent, status) if finally then busted.safe('finally', finally, element) end dexecAll('after_each', parent, true) diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 7f94b1a7..4dac437a 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -282,3 +282,27 @@ describe('tests aliases', function() assert.is_equal(8, test_val) end) end) + +describe('tests unsupported functions', function() + it('it block throws error on describe/context', function() + assert.has_error(describe, "'describe' not supported inside an 'it' block") + assert.has_error(context, "'context' not supported inside an 'it' block") + end) + + it('it block throws error on it/spec/test', function() + assert.has_error(it, "'it' not supported inside an 'it' block") + assert.has_error(spec, "'spec' not supported inside an 'it' block") + assert.has_error(test, "'test' not supported inside an 'it' block") + end) + + it('it block throws error on setup/before_each/after_each/teardown', function() + assert.has_error(setup, "'setup' not supported inside an 'it' block") + assert.has_error(before_each, "'before_each' not supported inside an 'it' block") + assert.has_error(after_each, "'after_each' not supported inside an 'it' block") + assert.has_error(teardown, "'teardown' not supported inside an 'it' block") + end) + + it('it block throws error on randomize', function() + assert.has_error(randomize, "'randomize' not supported inside an 'it' block") + end) +end) From cdb5913a9281ce42600f10070110be8199d27c50 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 1 Dec 2014 23:46:23 -0800 Subject: [PATCH 028/293] Unregister functions inside support functions Calling any of the busted registered functions from a support function is not valid, so throw an error if they are called from setup/teardown or before_each/after_each. --- busted/init.lua | 49 ++++++++++++++++++++++++----------------- spec/core_spec.lua | 54 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 30 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index d74df82d..39ecc767 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -11,28 +11,44 @@ local function shuffle(t) end return function(busted) + local function remove(descriptors, element) + for _, descriptor in ipairs(descriptors) do + element.env[descriptor] = function(...) + error("'" .. descriptor .. "' not supported inside current context block", 2) + end + end + end + + local function exec(descriptor, element) + if not element.env then element.env = {} end + + remove({ 'randomize' }, element) + remove({ 'pending' }, element) + remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) + remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) + + local ret = { busted.safe(descriptor, element.run, element) } + return unpack(ret) + end + local function execAll(descriptor, current, propagate) local parent = busted.context.parent(current) if propagate and parent then execAll(descriptor, parent, propagate) end - local list = current[descriptor] + local list = current[descriptor] or {} - if list then - for _, v in pairs(list) do - busted.safe(descriptor, v.run, v) - end + for _, v in pairs(list) do + exec(descriptor, v) end end local function dexecAll(descriptor, current, propagate) local parent = busted.context.parent(current) - local list = current[descriptor] + local list = current[descriptor] or {} - if list then - for _, v in pairs(list) do - busted.safe(descriptor, v.run, v) - end + for _, v in pairs(list) do + exec(descriptor, v) end if propagate and parent then dexecAll(descriptor, parent, propagate) end @@ -74,19 +90,12 @@ return function(busted) local it = function(element) local finally - local remove = function(descriptors) - for _, descriptor in ipairs(descriptors) do - element.env[descriptor] = function(...) - error("'"..descriptor.."' not supported inside an 'it' block", 2) - end - end - end if not element.env then element.env = {} end - remove({ 'randomize' }) - remove({ 'describe', 'context', 'it', 'spec', 'test' }) - remove({ 'setup', 'teardown', 'before_each', 'after_each' }) + remove({ 'randomize' }, element) + remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) + remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) element.env.finally = function(fn) finally = fn end element.env.pending = function(msg) busted.pending(msg) end diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 4dac437a..70166544 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -285,24 +285,58 @@ end) describe('tests unsupported functions', function() it('it block throws error on describe/context', function() - assert.has_error(describe, "'describe' not supported inside an 'it' block") - assert.has_error(context, "'context' not supported inside an 'it' block") + assert.has_error(describe, "'describe' not supported inside current context block") + assert.has_error(context, "'context' not supported inside current context block") end) it('it block throws error on it/spec/test', function() - assert.has_error(it, "'it' not supported inside an 'it' block") - assert.has_error(spec, "'spec' not supported inside an 'it' block") - assert.has_error(test, "'test' not supported inside an 'it' block") + assert.has_error(it, "'it' not supported inside current context block") + assert.has_error(spec, "'spec' not supported inside current context block") + assert.has_error(test, "'test' not supported inside current context block") end) it('it block throws error on setup/before_each/after_each/teardown', function() - assert.has_error(setup, "'setup' not supported inside an 'it' block") - assert.has_error(before_each, "'before_each' not supported inside an 'it' block") - assert.has_error(after_each, "'after_each' not supported inside an 'it' block") - assert.has_error(teardown, "'teardown' not supported inside an 'it' block") + assert.has_error(setup, "'setup' not supported inside current context block") + assert.has_error(before_each, "'before_each' not supported inside current context block") + assert.has_error(after_each, "'after_each' not supported inside current context block") + assert.has_error(teardown, "'teardown' not supported inside current context block") end) it('it block throws error on randomize', function() - assert.has_error(randomize, "'randomize' not supported inside an 'it' block") + assert.has_error(randomize, "'randomize' not supported inside current context block") + end) + + it('finaly block throws error on pending', function() + finally(function() + assert.has_error(pending, "'pending' not supported inside current context block") + end) + end) +end) + +describe('tests unsupported functions in setup/before_each/after_each/teardown', function() + local function testUnsupported() + assert.has_error(randomize, "'randomize' not supported inside current context block") + + assert.has_error(describe, "'describe' not supported inside current context block") + assert.has_error(context, "'context' not supported inside current context block") + + assert.has_error(pending, "'pending' not supported inside current context block") + + assert.has_error(it, "'it' not supported inside current context block") + assert.has_error(spec, "'spec' not supported inside current context block") + assert.has_error(test, "'test' not supported inside current context block") + + assert.has_error(setup, "'setup' not supported inside current context block") + assert.has_error(before_each, "'before_each' not supported inside current context block") + assert.has_error(after_each, "'after_each' not supported inside current context block") + assert.has_error(teardown, "'teardown' not supported inside current context block") + end + + setup(testUnsupported) + teardown(testUnsupported) + before_each(testUnsupported) + after_each(testUnsupported) + + it('tests nothing, all tests performed by support functions', function() end) end) From 21f7b411dab1bc6806a3738943e03349c743875c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 28 Nov 2014 23:50:51 -0800 Subject: [PATCH 029/293] Add commandline option to specify a random seed --- bin/busted | 15 ++++++++++++-- busted/init.lua | 6 ++++-- busted/outputHandlers/base.lua | 3 +++ spec/cl_random_seed.lua | 22 +++++++++++++++++++++ spec/cl_spec.lua | 36 ++++++++++++++++++++++++++++++++++ spec/randomize_spec.lua | 2 +- 6 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 spec/cl_random_seed.lua diff --git a/bin/busted b/bin/busted index aa4ee2bb..61b6ceec 100755 --- a/bin/busted +++ b/bin/busted @@ -18,6 +18,7 @@ require 'busted.init'(busted) local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' local defaultLoaders = 'lua,moonscript' local defaultPattern = '_spec' +local defaultSeed = tostring(os.time()) local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' @@ -35,6 +36,7 @@ cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) cli:add_option('-r, --run=RUN', 'config to run from .busted file') +cli:add_option('--seed=SEED', 'random seed value to use for randomizing test order', defaultSeed) cli:add_option('--lang=LANG', 'language for error messages', 'en') cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) cli:add_option('--helper=PATH', 'A helper script that is run before tests') @@ -79,8 +81,6 @@ end -- Load test directory local rootFile = path.normpath(path.join(fpath, cliArgs.ROOT)) -local pattern = cliArgs.pattern - local tags = {} local excludeTags = {} @@ -155,6 +155,16 @@ busted.subscribe({ 'failure' }, function(element, parent, status) return nil, true end) +-- Set up random seed +local randomseed = tonumber(cliArgs.seed) +if randomseed then + busted.randomseed = randomseed +else + print('Argument to --seed must be a number') + busted.randomseed = defaultSeed + errors = errors + 1 +end + -- Set up output handler to listen to events local outputHandlerOptions = { verbose = cliArgs.verbose, @@ -197,6 +207,7 @@ if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then busted.subscribe({ 'register', 'pending' }, checkTags, { priority = 1 }) end +local pattern = cliArgs.pattern local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) local fileList = testFileLoader(rootFile, pattern) if #fileList == 0 then diff --git a/busted/init.lua b/busted/init.lua index 39ecc767..015e66ba 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -1,6 +1,7 @@ math.randomseed(os.time()) -local function shuffle(t) +local function shuffle(t, seed) + if seed then math.randomseed(seed) end local n = #t while n >= 2 do local k = math.random(n) @@ -73,12 +74,13 @@ return function(busted) local randomize = false describe.env.randomize = function() + describe.randomseed = busted.randomseed randomize = true end if busted.safe('describe', describe.run, describe) == 'success' then if randomize then - shuffle(busted.context.children(describe)) + shuffle(busted.context.children(describe), busted.randomseed) end execAll('setup', describe) busted.execute(describe) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 08f2f9c7..77638010 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -129,6 +129,9 @@ return function(busted) handler.baseError = function(element, parent, message, debug) if element.descriptor == 'it' then + if parent.randomseed then + message = 'Random Seed: ' .. parent.randomseed .. '\n' .. message + end local id = tostring(element) handler.inProgress[id].message = message handler.inProgress[id].trace = debug diff --git a/spec/cl_random_seed.lua b/spec/cl_random_seed.lua new file mode 100644 index 00000000..ed2b486f --- /dev/null +++ b/spec/cl_random_seed.lua @@ -0,0 +1,22 @@ +-- supporting testfile; belongs to 'cl_spec.lua' +-- executed with --seed=12345 +local order = {} + +describe('Randomizing test order with pre-defined seed', function() + randomize() + + for i = 1, 10 do + it('does 10 its', function() + table.insert(order, i) + end) + end +end) + +describe('Order of tests ran', function() + randomize() + + it('randomized with known random seed', function() + local expected = { 9, 3, 5, 7, 6, 1, 8, 10, 4, 2 } + assert.are.same(expected, order) + end) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index d756f53e..91abb9cb 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -325,3 +325,39 @@ describe('Tests pending through the commandline', function() error_end() end) end) + +describe('Tests random seed through the commandline', function() + it('test seed value', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --seed=12345 --pattern=cl_random_seed.lua$') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) + + it('test invalid seed value defaults to a valid seed value', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --seed=abcd --pattern=cl_random_seed.lua$') + assert.is_false(success) + assert.is_equal(2, exitcode) -- fails cl_random_seed test +1 error + error_end() + end) + + it('test failure outputs random seed value', function() + error_start() + local result = run('bin/busted --seed=789 --pattern=cl_random_seed.lua$') + local seed = result:match('Random Seed: (%d+)\n') + assert.is_equal(789, tonumber(seed)) + error_end() + end) + + it('test non-randomized failure does not output seed value', function() + error_start() + local result = run('bin/busted --seed=789 --pattern=cl_two_failures.lua$') + local seed = result:match('Random Seed:') + assert.is_equal(nil, seed) + error_end() + end) +end) diff --git a/spec/randomize_spec.lua b/spec/randomize_spec.lua index 4d6bede2..55208a81 100644 --- a/spec/randomize_spec.lua +++ b/spec/randomize_spec.lua @@ -7,7 +7,7 @@ describe('Randomizing test order', function() for i = 1, 100 do table.insert(unexpected, i) - it('does 1000 its', function() + it('does 100 its', function() table.insert(order, i) end) end From 99b3d58a1ab1edc1f977a3ab46d8e32d05e5678a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 29 Nov 2014 01:20:29 -0800 Subject: [PATCH 030/293] Add support for setup/teardown in file context --- busted/init.lua | 2 ++ spec/file_context_support_spec.lua | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 spec/file_context_support_spec.lua diff --git a/busted/init.lua b/busted/init.lua index 015e66ba..df10ba3f 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -59,7 +59,9 @@ return function(busted) busted.publish({ 'file', 'start' }, file.name) if busted.safe('file', file.run, file, true) == 'success' then + execAll('setup', file) busted.execute(file) + dexecAll('teardown', file) end busted.publish({ 'file', 'end' }, file.name) diff --git a/spec/file_context_support_spec.lua b/spec/file_context_support_spec.lua new file mode 100644 index 00000000..16a12a35 --- /dev/null +++ b/spec/file_context_support_spec.lua @@ -0,0 +1,28 @@ +local egg = '' + +setup(function() + egg = egg..'S' +end) + +teardown(function() + egg = egg..'T' + assert.equal('Sb1ab2aT', egg) +end) + +before_each(function() + egg = egg..'b' +end) + +after_each(function() + egg = egg..'a' +end) + +it('file context before_each after_each egg test 1', function() + assert.equal('Sb', egg) + egg = egg..'1' +end) + +it('file context before_each after_each egg test 2', function() + assert.equal('Sb1ab', egg) + egg = egg..'2' +end) From c1550ca9935efa640d049b4c340a63b0b1af7e1b Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 29 Nov 2014 23:29:32 -0800 Subject: [PATCH 031/293] Add support for randomize in file context --- busted/core.lua | 8 +++++--- busted/init.lua | 16 ++++++++++++++-- spec/file_randomize_spec.lua | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 spec/file_randomize_spec.lua diff --git a/busted/core.lua b/busted/core.lua index 913a10be..dbe9a61f 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -118,12 +118,14 @@ return function() setfenv(f, env) end - function busted.safe(descriptor, run, element, setenv) - if setenv and (type(run) == 'function' or getmetatable(run).__call) then + function busted.wrapEnv(callable) + if (type(callable) == 'function' or getmetatable(callable).__call) then -- prioritize __call if it exists, like in files - environment.wrap(getmetatable(run).__call or run) + environment.wrap(getmetatable(callable).__call or callable) end + end + function busted.safe(descriptor, run, element) busted.context.push(element) local trace, message local status = 'success' diff --git a/busted/init.lua b/busted/init.lua index df10ba3f..1864302f 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -58,7 +58,19 @@ return function(busted) local file = function(file) busted.publish({ 'file', 'start' }, file.name) - if busted.safe('file', file.run, file, true) == 'success' then + busted.wrapEnv(file.run) + if not file.env then file.env = {} end + + local randomize = false + file.env.randomize = function() + randomize = true + end + + if busted.safe('file', file.run, file) == 'success' then + if randomize then + file.randomseed = busted.randomseed + shuffle(busted.context.children(file), busted.randomseed) + end execAll('setup', file) busted.execute(file) dexecAll('teardown', file) @@ -76,12 +88,12 @@ return function(busted) local randomize = false describe.env.randomize = function() - describe.randomseed = busted.randomseed randomize = true end if busted.safe('describe', describe.run, describe) == 'success' then if randomize then + describe.randomseed = busted.randomseed shuffle(busted.context.children(describe), busted.randomseed) end execAll('setup', describe) diff --git a/spec/file_randomize_spec.lua b/spec/file_randomize_spec.lua new file mode 100644 index 00000000..a7cd7fc5 --- /dev/null +++ b/spec/file_randomize_spec.lua @@ -0,0 +1,16 @@ +local unexpected = {} +local order = {} + +randomize() + +for i = 1, 100 do + table.insert(unexpected, i) + + it('does 100 its', function() + table.insert(order, i) + end) +end + +teardown(function() + assert.are_not.same(unexpected, order) +end) From 69a2c1c1f901b1952419c5d89cb3b005404c3146 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 3 Dec 2014 22:30:45 -0800 Subject: [PATCH 032/293] Add commandline flag to force randomization --- bin/busted | 5 +++-- busted/init.lua | 4 ++-- spec/cl_randomize.lua | 18 ++++++++++++++++++ spec/cl_spec.lua | 11 +++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 spec/cl_randomize.lua diff --git a/bin/busted b/bin/busted index 61b6ceec..7e22259d 100755 --- a/bin/busted +++ b/bin/busted @@ -42,9 +42,9 @@ cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) cli:add_option('--helper=PATH', 'A helper script that is run before tests') cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') - cli:add_flag('-v, --verbose', 'verbose output of errors') cli:add_flag('-s, --enable-sound', 'executes `say` command if available') +cli:add_flag('--randomize', 'force randomized test order') cli:add_flag('--suppress-pending', 'suppress `pending` test output') cli:add_flag('--defer-print', 'defer print to when test suite is complete') @@ -155,7 +155,8 @@ busted.subscribe({ 'failure' }, function(element, parent, status) return nil, true end) --- Set up random seed +-- Set up randomization options +busted.randomize = cliArgs.randomize local randomseed = tonumber(cliArgs.seed) if randomseed then busted.randomseed = randomseed diff --git a/busted/init.lua b/busted/init.lua index 1864302f..dbfb7e09 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -61,7 +61,7 @@ return function(busted) busted.wrapEnv(file.run) if not file.env then file.env = {} end - local randomize = false + local randomize = busted.randomize file.env.randomize = function() randomize = true end @@ -86,7 +86,7 @@ return function(busted) if not describe.env then describe.env = {} end - local randomize = false + local randomize = busted.randomize describe.env.randomize = function() randomize = true end diff --git a/spec/cl_randomize.lua b/spec/cl_randomize.lua new file mode 100644 index 00000000..5a811214 --- /dev/null +++ b/spec/cl_randomize.lua @@ -0,0 +1,18 @@ +-- supporting testfile; belongs to 'cl_spec.lua' +local unexpected = {} +local order = {} + +describe('Randomizing test order with --randomize flag', function() + for i = 1, 100 do + table.insert(unexpected, i) + + it('does 100 its', function() + table.insert(order, i) + end) + end + + teardown('runs tests in randomized order', function() + assert.are_not.same(unexpected, order) + end) +end) + diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 91abb9cb..2afae66c 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -361,3 +361,14 @@ describe('Tests random seed through the commandline', function() error_end() end) end) + +describe('Tests randomize commandline option', function() + it('forces test randomization for non-randomized tests', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --randomize --pattern=cl_randomize.lua$') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) +end) From 18eb8a10f89fdd6291e8f7f9df9df2a7dd1fdbb7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 30 Nov 2014 01:02:12 -0800 Subject: [PATCH 033/293] Refactor format of error descriptions Format error descriptions to be the same as failure descriptions whenever possible. The only time this is not possible is when trace information is not present for the error. In such a case just output error description without using any trace information. --- busted/outputHandlers/plainTerminal.lua | 33 ++++++++++++++----------- busted/outputHandlers/utfTerminal.lua | 33 ++++++++++++++----------- spec/cl_spec.lua | 18 +++++++++----- 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index d9a9e659..9db6ad2d 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -26,30 +26,35 @@ return function(options, busted) return string end + local failureMessage = function(failure) + local string + if type(failure.message) == 'string' then + string = failure.message + elseif failure.message == nil then + string = 'Nil error' + else + string = pretty.write(failure.message) + end + + return string + end + local failureDescription = function(failure, isError) local string = s('output.failure') .. ' → ' - if isError then - string = s('output.error') + string = s('output.error') .. ' → ' + end - if failure.message then - string = string .. ' → ' .. failure.message .. '\n' - end + if not failure.trace or not failure.trace.short_src then string = string .. + failureMessage(failure) .. '\n' .. handler.getFullName(failure) else string = string .. failure.trace.short_src .. ' @ ' .. failure.trace.currentline .. '\n' .. - handler.getFullName(failure) .. '\n' - - if type(failure.message) == 'string' then - string = string .. failure.message - elseif failure.message == nil then - string = string .. 'Nil error' - else - string = string .. pretty.write(failure.message) - end + handler.getFullName(failure) .. '\n' .. + failureMessage(failure) end if options.verbose and failure.trace and failure.trace.traceback then diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 2f320257..40b199c0 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -27,30 +27,35 @@ return function(options, busted) return string end + local failureMessage = function(failure) + local string + if type(failure.message) == 'string' then + string = failure.message + elseif failure.message == nil then + string = 'Nil error' + else + string = pretty.write(failure.message) + end + + return string + end + local failureDescription = function(failure, isError) local string = ansicolors('%{red}' .. s('output.failure')) .. ' → ' - if isError then - string = ansicolors('%{magenta}' .. s('output.error')) + string = ansicolors('%{magenta}' .. s('output.error')) .. ' → ' + end - if failure.message then - string = string .. ' → ' .. ansicolors('%{cyan}' .. failure.message) .. '\n' - end + if not failure.trace or not failure.trace.short_src then string = string .. + ansicolors('%{cyan}' .. failureMessage(failure)) .. '\n' .. ansicolors('%{bright}' .. handler.getFullName(failure)) else string = string .. ansicolors('%{cyan}' .. failure.trace.short_src) .. ' @ ' .. ansicolors('%{cyan}' .. failure.trace.currentline) .. '\n' .. - ansicolors('%{bright}' .. handler.getFullName(failure)) .. '\n' - - if type(failure.message) == 'string' then - string = string .. failure.message - elseif failure.message == nil then - string = string .. 'Nil error' - else - string = string .. pretty.write(failure.message) - end + ansicolors('%{bright}' .. handler.getFullName(failure)) .. '\n' .. + failureMessage(failure) end if options.verbose and failure.trace and failure.trace.traceback then diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 2afae66c..f5083e33 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -250,9 +250,12 @@ describe('Tests error messages through the command line', function() it('when throwing errors in a test', function() error_start() local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') - local errmsg = result:match('(Error → .-)\n') - local expected = "Error → ./spec/cl_errors.lua:6: force an error" - assert.is_equal(expected, errmsg) + local err = result:match('(Error → .-)\n') + local errmsg = result:match('\n(%./spec/.-)\n') + local expectedErr = "Error → ./spec/cl_errors.lua @ 6" + local expectedMsg = "./spec/cl_errors.lua:6: force an error" + assert.is_equal(expectedErr, err) + assert.is_equal(expectedMsg, errmsg) error_end() end) @@ -268,9 +271,12 @@ describe('Tests error messages through the command line', function() it('when a testfile throws errors', function() error_start() local result = run('bin/busted --output=plainTerminal --pattern=cl_execute_fail.lua$') - local errmsg = result:match('(Error → .-)\n') - local expected = 'Error → ./spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' - assert.is_equal(expected, errmsg) + local err = result:match('(Error → .-)\n') + local errmsg = result:match('\n(%./spec/cl_execute_fail%.lua:%d+:.-)\n') + local expectedErr = 'Error → ./spec/cl_execute_fail.lua @ 4' + local expectedMsg = './spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' + assert.is_equal(expectedErr, err) + assert.is_equal(expectedMsg, errmsg) error_end() end) From cae75a6c031674eeb729f62839a6fa9a28cefcaa Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 2 Dec 2014 00:59:36 -0800 Subject: [PATCH 034/293] Skip tests if setup fails If setup fails, then do not run any tests in the current context block. --- busted/init.lua | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index dbfb7e09..3b30dd17 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -39,20 +39,28 @@ return function(busted) local list = current[descriptor] or {} + local status = true for _, v in pairs(list) do - exec(descriptor, v) + if exec(descriptor, v) ~= 'success' then + status = nil + end end + return status end local function dexecAll(descriptor, current, propagate) local parent = busted.context.parent(current) local list = current[descriptor] or {} + local status = true for _, v in pairs(list) do - exec(descriptor, v) + if exec(descriptor, v) ~= 'success' then + status = nil + end end if propagate and parent then dexecAll(descriptor, parent, propagate) end + return status end local file = function(file) @@ -62,17 +70,16 @@ return function(busted) if not file.env then file.env = {} end local randomize = busted.randomize - file.env.randomize = function() - randomize = true - end + file.env.randomize = function() randomize = true end if busted.safe('file', file.run, file) == 'success' then if randomize then file.randomseed = busted.randomseed shuffle(busted.context.children(file), busted.randomseed) end - execAll('setup', file) - busted.execute(file) + if execAll('setup', file) then + busted.execute(file) + end dexecAll('teardown', file) end @@ -87,17 +94,16 @@ return function(busted) if not describe.env then describe.env = {} end local randomize = busted.randomize - describe.env.randomize = function() - randomize = true - end + describe.env.randomize = function() randomize = true end if busted.safe('describe', describe.run, describe) == 'success' then if randomize then describe.randomseed = busted.randomseed shuffle(busted.context.children(describe), busted.randomseed) end - execAll('setup', describe) - busted.execute(describe) + if execAll('setup', describe) then + busted.execute(describe) + end dexecAll('teardown', describe) end From 3b93e86f7cb971792f2d1d75cad5a5c769b0cb89 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 2 Dec 2014 01:01:28 -0800 Subject: [PATCH 035/293] Skip test if before_each fails Do not run current test if before_each fails. In addition, a failure in before_each or after_each should cause the current test to also fail. When this happens, add to error message that before_each and/or after_each failed. When a before_each fails, stop running before_each's in child context blocks, and run after_each's starting from the last executed context block. --- busted/init.lua | 57 ++++++++++++++++++++++++++++------ busted/outputHandlers/base.lua | 2 +- spec/cl_spec.lua | 2 +- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 3b30dd17..46800a17 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -35,7 +35,12 @@ return function(busted) local function execAll(descriptor, current, propagate) local parent = busted.context.parent(current) - if propagate and parent then execAll(descriptor, parent, propagate) end + if propagate and parent then + local success, ancestor = execAll(descriptor, parent, propagate) + if not success then + return success, ancestor + end + end local list = current[descriptor] or {} @@ -45,7 +50,7 @@ return function(busted) status = nil end end - return status + return status, current end local function dexecAll(descriptor, current, propagate) @@ -59,10 +64,30 @@ return function(busted) end end - if propagate and parent then dexecAll(descriptor, parent, propagate) end + if propagate and parent then + if not dexecAll(descriptor, parent, propagate) then + status = nil + end + end return status end + local function mergeStatus(status1, status2) + local isSuccess = function(status) return (status == true or status == 'success') end + local map = { + ['success'] = 'success', + ['pending'] = 'pending', + ['failure'] = 'failure', + ['error'] = 'error', + ['true'] = 'success', + ['false'] = 'failure', + ['nil'] = 'error', + } + if (isSuccess(status1)) then return map[tostring(status2)] end + if (isSuccess(status2)) then return map[tostring(status1)] end + return (status1 == 'pending' and map[tostring(status2)] or map[tostring(status1)]) + end + local file = function(file) busted.publish({ 'file', 'start' }, file.name) @@ -113,6 +138,8 @@ return function(busted) local it = function(element) local finally + busted.publish({ 'test', 'start' }, element, parent) + if not element.env then element.env = {} end remove({ 'randomize' }, element) @@ -121,18 +148,30 @@ return function(busted) element.env.finally = function(fn) finally = fn end element.env.pending = function(msg) busted.pending(msg) end - local parent = busted.context.parent(element) + local status = 'success' + local supportError = function(descriptor) + if element.message then element.message = element.message .. '\n' end + element.message = (element.message or '') .. 'Error in ' .. descriptor + status = mergeStatus(status, 'error') + end - execAll('before_each', parent, true) + local parent = busted.context.parent(element) + local pass, ancestor = execAll('before_each', parent, true) - busted.publish({ 'test', 'start' }, element, parent) + if pass then + status = busted.safe('element', element.run, element) + else + supportError('before_each') + end - local status = busted.safe('element', element.run, element) if not element.env.done then remove({ 'pending' }, element) + if finally then status = mergeStatus(status, busted.safe('finally', finally, element)) end + if not dexecAll('after_each', ancestor, true) then + supportError('after_each') + end + busted.publish({ 'test', 'end' }, element, parent, status) - if finally then busted.safe('finally', finally, element) end - dexecAll('after_each', parent, true) end end diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 77638010..bda35c4c 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -104,7 +104,7 @@ return function(busted) isError = true end - insertTable[id] = handler.format(element, parent, nil, debug, isError) + insertTable[id] = handler.format(element, parent, element.message, debug, isError) if handler.inProgress[id] then for k, v in pairs(handler.inProgress[id]) do diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index f5083e33..e6052f67 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -180,7 +180,7 @@ describe('Tests failing tests through the commandline', function() error_start() local result = run('bin/busted --output=plainTerminal --pattern=cl_failing_support.lua$') local _, numErrors = result:gsub('Error → .-\n','') - assert.is_equal(8, numErrors) + assert.is_equal(12, numErrors) error_end() end) end) From 32af9a72983040e54025796382c69e173386569a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 5 Dec 2014 00:54:31 -0800 Subject: [PATCH 036/293] Refactor how test phase status results are merged Use a status object to store the result of a context block execution. The result of each execution can then be used to update the status object instance, which makes failures/errors sticky. --- busted/core.lua | 4 +++- busted/init.lua | 54 +++++++++++++++++------------------------------ busted/status.lua | 43 +++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 36 deletions(-) create mode 100644 busted/status.lua diff --git a/busted/core.lua b/busted/core.lua index dbe9a61f..4d4e214a 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -39,6 +39,8 @@ return function() busted.executors = {} local executors = {} + busted.status = require 'busted.status' + busted.getTrace = function(element, level, msg) level = level or 3 @@ -140,7 +142,7 @@ return function() if not ret[1] then busted.publish({ status, descriptor }, element, busted.context.parent(element), message, trace) end - ret[1] = status + ret[1] = busted.status(status) busted.context.pop() return unpack(ret) diff --git a/busted/init.lua b/busted/init.lua index 46800a17..f09f97b3 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -44,48 +44,32 @@ return function(busted) local list = current[descriptor] or {} - local status = true + local success = true for _, v in pairs(list) do - if exec(descriptor, v) ~= 'success' then - status = nil + if not exec(descriptor, v):success() then + success = nil end end - return status, current + return success, current end local function dexecAll(descriptor, current, propagate) local parent = busted.context.parent(current) local list = current[descriptor] or {} - local status = true + local success = true for _, v in pairs(list) do - if exec(descriptor, v) ~= 'success' then - status = nil + if not exec(descriptor, v):success() then + success = nil end end if propagate and parent then if not dexecAll(descriptor, parent, propagate) then - status = nil + success = nil end end - return status - end - - local function mergeStatus(status1, status2) - local isSuccess = function(status) return (status == true or status == 'success') end - local map = { - ['success'] = 'success', - ['pending'] = 'pending', - ['failure'] = 'failure', - ['error'] = 'error', - ['true'] = 'success', - ['false'] = 'failure', - ['nil'] = 'error', - } - if (isSuccess(status1)) then return map[tostring(status2)] end - if (isSuccess(status2)) then return map[tostring(status1)] end - return (status1 == 'pending' and map[tostring(status2)] or map[tostring(status1)]) + return success end local file = function(file) @@ -97,7 +81,7 @@ return function(busted) local randomize = busted.randomize file.env.randomize = function() randomize = true end - if busted.safe('file', file.run, file) == 'success' then + if busted.safe('file', file.run, file):success() then if randomize then file.randomseed = busted.randomseed shuffle(busted.context.children(file), busted.randomseed) @@ -121,7 +105,7 @@ return function(busted) local randomize = busted.randomize describe.env.randomize = function() randomize = true end - if busted.safe('describe', describe.run, describe) == 'success' then + if busted.safe('describe', describe.run, describe):success() then if randomize then describe.randomseed = busted.randomseed shuffle(busted.context.children(describe), busted.randomseed) @@ -148,30 +132,30 @@ return function(busted) element.env.finally = function(fn) finally = fn end element.env.pending = function(msg) busted.pending(msg) end - local status = 'success' - local supportError = function(descriptor) + local status = busted.status('success') + local updateErrorStatus = function(descriptor) if element.message then element.message = element.message .. '\n' end element.message = (element.message or '') .. 'Error in ' .. descriptor - status = mergeStatus(status, 'error') + status:update('error') end local parent = busted.context.parent(element) local pass, ancestor = execAll('before_each', parent, true) if pass then - status = busted.safe('element', element.run, element) + status:update(busted.safe('element', element.run, element)) else - supportError('before_each') + updateErrorStatus('before_each') end if not element.env.done then remove({ 'pending' }, element) - if finally then status = mergeStatus(status, busted.safe('finally', finally, element)) end + if finally then status:update(busted.safe('finally', finally, element)) end if not dexecAll('after_each', ancestor, true) then - supportError('after_each') + updateErrorStatus('after_each') end - busted.publish({ 'test', 'end' }, element, parent, status) + busted.publish({ 'test', 'end' }, element, parent, tostring(status)) end end diff --git a/busted/status.lua b/busted/status.lua new file mode 100644 index 00000000..c68ce7fc --- /dev/null +++ b/busted/status.lua @@ -0,0 +1,43 @@ +local function get_status(status) + local smap = { + ['success'] = 'success', + ['pending'] = 'pending', + ['failure'] = 'failure', + ['error'] = 'error', + ['true'] = 'success', + ['false'] = 'failure', + ['nil'] = 'error', + } + return smap[tostring(status)] or 'error' +end + +return function(inital_status) + local objstat = get_status(inital_status) + local obj = { + success = function(self) return (objstat == 'success') end, + pending = function(self) return (objstat == 'pending') end, + failure = function(self) return (objstat == 'failure') end, + error = function(self) return (objstat == 'error') end, + + get = function(self) + return objstat + end, + + set = function(self, status) + objstat = get_status(status) + end, + + update = function(self, status) + -- prefer current failure/error status over new status + status = get_status(status) + if objstat == 'success' or (objstat == 'pending' and status ~= 'success') then + objstat = status + end + end + } + + return setmetatable(obj, { + __index = {}, + __tostring = function(self) return objstat end + }) +end From 8ebb063818a7918b7f92740bcf3922f885ff58ac Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 6 Dec 2014 00:50:24 -0800 Subject: [PATCH 037/293] Fix tests to work with differnt versions fo Lua --- spec/cl_random_seed.lua | 13 ++++++++++++- spec/cl_spec.lua | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/spec/cl_random_seed.lua b/spec/cl_random_seed.lua index ed2b486f..9dca26ba 100644 --- a/spec/cl_random_seed.lua +++ b/spec/cl_random_seed.lua @@ -16,7 +16,18 @@ describe('Order of tests ran', function() randomize() it('randomized with known random seed', function() - local expected = { 9, 3, 5, 7, 6, 1, 8, 10, 4, 2 } + math.randomseed(12345) + local t = {} + for i = 1, 10 do + table.insert(t, i) + end + local n = #t + while n >= 1 do + local k = math.random(n) + t[n], t[k] = t[k], t[n] + n = n - 1 + end + local expected = t assert.are.same(expected, order) end) end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index e6052f67..0b600e78 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -262,8 +262,8 @@ describe('Tests error messages through the command line', function() it('when running a non-compiling testfile', function() error_start() local result = run('bin/busted --output=plainTerminal --pattern=cl_compile_fail.lua$') - local errmsg = result:match('(Error → .-)\n') - local expected = "Error → ./spec/cl_compile_fail.lua:3: '=' expected near 'here'" + local errmsg = result:match('(Error → .-:%d+:) ') + local expected = "Error → ./spec/cl_compile_fail.lua:3:" assert.is_equal(expected, errmsg) error_end() end) From 40a9ab2b5119224ad6aedd117ac20ded016028ef Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 6 Dec 2014 01:27:38 -0800 Subject: [PATCH 038/293] Add busted.status to busted rockspec --- busted-2.0.rc3-0.rockspec | 1 + 1 file changed, 1 insertion(+) diff --git a/busted-2.0.rc3-0.rockspec b/busted-2.0.rc3-0.rockspec index 2bc7f332..8dd6c8d8 100644 --- a/busted-2.0.rc3-0.rockspec +++ b/busted-2.0.rc3-0.rockspec @@ -36,6 +36,7 @@ build = { ['busted.environment'] = 'busted/environment.lua', ['busted.compatibility'] = 'busted/compatibility.lua', ['busted.done'] = 'busted/done.lua', + ['busted.status'] = 'busted/status.lua', ['busted.init'] = 'busted/init.lua', ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', From 32a96acdbd308e293b931bd9dea7cb0e3ea43a9f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 6 Dec 2014 22:09:53 -0800 Subject: [PATCH 039/293] Report the test file@line in failure/error header Since assertion failures and error messages report the file and line number of the failure/error site, it is not necessary to also show this information in the failure/error header. Therefore, update the header message to report the file and line number of the declared test instead. --- busted/outputHandlers/TAP.lua | 2 +- busted/outputHandlers/base.lua | 2 ++ busted/outputHandlers/plainTerminal.lua | 6 +++--- busted/outputHandlers/utfTerminal.lua | 6 +++--- spec/cl_spec.lua | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index b1fd18d6..2f26edda 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -42,7 +42,7 @@ return function(options, busted) end print( failure:format( counter, handler.format(t).name )) - print('# ' .. t.trace.short_src .. ' @ ' .. t.trace.currentline) + print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) print('# Failure message: ' .. message:gsub('\n', '\n# ' )) end diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index bda35c4c..4961d1ae 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -51,10 +51,12 @@ return function(busted) handler.format = function(element, parent, message, debug, isError) local formatted = { trace = debug or element.trace, + element = element, name = handler.getFullName(element), message = message, isError = isError } + formatted.element.trace = element.trace or debug return formatted end diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 9db6ad2d..89839e77 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -45,14 +45,14 @@ return function(options, busted) string = s('output.error') .. ' → ' end - if not failure.trace or not failure.trace.short_src then + if not failure.element.trace or not failure.element.trace.short_src then string = string .. failureMessage(failure) .. '\n' .. handler.getFullName(failure) else string = string .. - failure.trace.short_src .. ' @ ' .. - failure.trace.currentline .. '\n' .. + failure.element.trace.short_src .. ' @ ' .. + failure.element.trace.currentline .. '\n' .. handler.getFullName(failure) .. '\n' .. failureMessage(failure) end diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 40b199c0..1e8de3d5 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -46,14 +46,14 @@ return function(options, busted) string = ansicolors('%{magenta}' .. s('output.error')) .. ' → ' end - if not failure.trace or not failure.trace.short_src then + if not failure.element.trace or not failure.element.trace.short_src then string = string .. ansicolors('%{cyan}' .. failureMessage(failure)) .. '\n' .. ansicolors('%{bright}' .. handler.getFullName(failure)) else string = string .. - ansicolors('%{cyan}' .. failure.trace.short_src) .. ' @ ' .. - ansicolors('%{cyan}' .. failure.trace.currentline) .. '\n' .. + ansicolors('%{cyan}' .. failure.element.trace.short_src) .. ' @ ' .. + ansicolors('%{cyan}' .. failure.element.trace.currentline) .. '\n' .. ansicolors('%{bright}' .. handler.getFullName(failure)) .. '\n' .. failureMessage(failure) end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 0b600e78..121a8f87 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -252,7 +252,7 @@ describe('Tests error messages through the command line', function() local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') local err = result:match('(Error → .-)\n') local errmsg = result:match('\n(%./spec/.-)\n') - local expectedErr = "Error → ./spec/cl_errors.lua @ 6" + local expectedErr = "Error → ./spec/cl_errors.lua @ 5" local expectedMsg = "./spec/cl_errors.lua:6: force an error" assert.is_equal(expectedErr, err) assert.is_equal(expectedMsg, errmsg) From 9e65c3f13e66d4bfc7809a59b43ca6ede6eccb5f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 9 Dec 2014 00:02:22 -0800 Subject: [PATCH 040/293] Fix use of handler.getFullName in output handlers The function handler.getFullName() was not being used correctly in the plainTerminal and utfTerminal output handlers. The getFullName() function should be passed a context element as input, but these output handlers were passing the results of handler.format(), which is not a context element, and already has a 'name' field that is the result of handler.getFullName(). The TAP output handler was calling handler.format() on tables that were already the result of a previous call to handler.format(). In this case, just use the pre-formatted table directly. Remove unused local function getFullName() in TAP output handler. --- busted/outputHandlers/TAP.lua | 18 ++---------------- busted/outputHandlers/base.lua | 2 -- busted/outputHandlers/plainTerminal.lua | 6 +++--- busted/outputHandlers/utfTerminal.lua | 6 +++--- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index 2f26edda..c9a8ebcb 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -4,20 +4,6 @@ local tablex = require 'pl.tablex' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) - local getFullName = function(context) - local parent = context.parent - local names = { (context.name or context.descriptor) } - - while parent and (parent.name or parent.descriptor) and - parent.descriptor ~= 'file' do - - table.insert(names, 1, parent.name or parent.descriptor) - parent = busted.context.parent(parent) - end - - return table.concat(names, ' ') - end - handler.suiteEnd = function(name, parent) local total = handler.successesCount + handler.errorsCount + handler.failuresCount print('1..' .. total) @@ -28,7 +14,7 @@ return function(options, busted) for i,t in pairs(handler.successes) do counter = counter + 1 - print( success:format( counter, handler.format(t).name )) + print( success:format( counter, t.name )) end for i,t in pairs(handler.failures) do @@ -41,7 +27,7 @@ return function(options, busted) message = pretty.write(message) end - print( failure:format( counter, handler.format(t).name )) + print( failure:format( counter, t.name )) print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) print('# Failure message: ' .. message:gsub('\n', '\n# ' )) end diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 4961d1ae..78f9f168 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -39,7 +39,6 @@ return function(busted) while parent and (parent.name or parent.descriptor) and parent.descriptor ~= 'file' do - current_context = context.parent table.insert(names, 1, parent.name or parent.descriptor) parent = busted.context.parent(parent) end @@ -47,7 +46,6 @@ return function(busted) return table.concat(names, ' ') end - handler.format = function(element, parent, message, debug, isError) local formatted = { trace = debug or element.trace, diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 89839e77..7a893b23 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -10,7 +10,7 @@ return function(options, busted) local pendingDot = '.' local pendingDescription = function(pending) - local name = handler.getFullName(pending) + local name = pending.name local string = s('output.pending') .. ' → ' .. pending.trace.short_src .. ' @ ' .. @@ -48,12 +48,12 @@ return function(options, busted) if not failure.element.trace or not failure.element.trace.short_src then string = string .. failureMessage(failure) .. '\n' .. - handler.getFullName(failure) + failure.name else string = string .. failure.element.trace.short_src .. ' @ ' .. failure.element.trace.currentline .. '\n' .. - handler.getFullName(failure) .. '\n' .. + failure.name .. '\n' .. failureMessage(failure) end diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 1e8de3d5..eef64911 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -11,7 +11,7 @@ return function(options, busted) local pendingDot = ansicolors('%{yellow}●') local pendingDescription = function(pending) - local name = handler.getFullName(pending) + local name = pending.name local string = ansicolors('%{yellow}' .. s('output.pending')) .. ' → ' .. ansicolors('%{cyan}' .. pending.trace.short_src) .. ' @ ' .. @@ -49,12 +49,12 @@ return function(options, busted) if not failure.element.trace or not failure.element.trace.short_src then string = string .. ansicolors('%{cyan}' .. failureMessage(failure)) .. '\n' .. - ansicolors('%{bright}' .. handler.getFullName(failure)) + ansicolors('%{bright}' .. failure.name) else string = string .. ansicolors('%{cyan}' .. failure.element.trace.short_src) .. ' @ ' .. ansicolors('%{cyan}' .. failure.element.trace.currentline) .. '\n' .. - ansicolors('%{bright}' .. handler.getFullName(failure)) .. '\n' .. + ansicolors('%{bright}' .. failure.name) .. '\n' .. failureMessage(failure) end From 02183666aed2835151a7191492d43005500902a7 Mon Sep 17 00:00:00 2001 From: Robert Ditthardt Date: Wed, 17 Dec 2014 13:00:03 -0800 Subject: [PATCH 041/293] Version v2.0.rc4 --- busted-2.0.rc3-0.rockspec | 75 --------------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 busted-2.0.rc3-0.rockspec diff --git a/busted-2.0.rc3-0.rockspec b/busted-2.0.rc3-0.rockspec deleted file mode 100644 index 8dd6c8d8..00000000 --- a/busted-2.0.rc3-0.rockspec +++ /dev/null @@ -1,75 +0,0 @@ -package = 'busted' -version = '2.0.rc3-0' -source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc3.tar.gz', - dir = 'busted-2.0.rc3' -} -description = { - summary = 'Elegant Lua unit testing.', - detailed = [[ - An elegant, extensible, testing framework. - Ships with a large amount of useful asserts, - plus the ability to write your own. Output - in pretty or plain terminal format, JSON, - or TAP for CI integration. Great for TDD - and unit, integration, and functional tests. - ]], - homepage = 'http://olivinelabs.com/busted/', - license = 'MIT ' -} -dependencies = { - 'lua >= 5.1', - 'lua_cliargs >= 2.0', - 'luafilesystem >= 1.5.0', - 'dkjson >= 2.1.0', - 'say >= 1.2-1', - 'luassert >= 1.7.1-0', - 'ansicolors >= 1.0-1', - 'penlight >= 1.0.0-1', - 'mediator_lua >= 1.1-3', -} -build = { - type = 'builtin', - modules = { - ['busted.core'] = 'busted/core.lua', - ['busted.context'] = 'busted/context.lua', - ['busted.environment'] = 'busted/environment.lua', - ['busted.compatibility'] = 'busted/compatibility.lua', - ['busted.done'] = 'busted/done.lua', - ['busted.status'] = 'busted/status.lua', - ['busted.init'] = 'busted/init.lua', - - ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', - ['busted.modules.luacov'] = 'busted/modules/luacov.lua', - ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', - ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', - - ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', - ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', - ['busted.modules.files.terra'] = 'busted/modules/files/terra.lua', - - ['busted.outputHandlers.base'] = 'busted/outputHandlers/base.lua', - ['busted.outputHandlers.utfTerminal'] = 'busted/outputHandlers/utfTerminal.lua', - ['busted.outputHandlers.plainTerminal'] = 'busted/outputHandlers/plainTerminal.lua', - ['busted.outputHandlers.TAP'] = 'busted/outputHandlers/TAP.lua', - ['busted.outputHandlers.json'] = 'busted/outputHandlers/json.lua', - ['busted.outputHandlers.junit'] = 'busted/outputHandlers/junit.lua', - ['busted.outputHandlers.sound'] = 'busted/outputHandlers/sound.lua', - - ['busted.languages.en'] = 'busted/languages/en.lua', - ['busted.languages.ar'] = 'busted/languages/ar.lua', - ['busted.languages.de'] = 'busted/languages/de.lua', - ['busted.languages.fr'] = 'busted/languages/fr.lua', - ['busted.languages.ja'] = 'busted/languages/ja.lua', - ['busted.languages.nl'] = 'busted/languages/nl.lua', - ['busted.languages.ru'] = 'busted/languages/ru.lua', - ['busted.languages.th'] = 'busted/languages/th.lua', - ['busted.languages.ua'] = 'busted/languages/ua.lua', - ['busted.languages.zh'] = 'busted/languages/zh.lua', - }, - install = { - bin = { - ['busted'] = 'bin/busted' - } - } -} From bfbc9ca415de95773d1fcdf96dcb22aa5cecb440 Mon Sep 17 00:00:00 2001 From: Robert Ditthardt Date: Wed, 17 Dec 2014 13:03:06 -0800 Subject: [PATCH 042/293] Rockspec --- busted-2.0.rc4-0.rockspec | 75 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 busted-2.0.rc4-0.rockspec diff --git a/busted-2.0.rc4-0.rockspec b/busted-2.0.rc4-0.rockspec new file mode 100644 index 00000000..f51fd056 --- /dev/null +++ b/busted-2.0.rc4-0.rockspec @@ -0,0 +1,75 @@ +package = 'busted' +version = '2.0.rc4-0' +source = { + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc4.tar.gz', + dir = 'busted-2.0.rc4' +} +description = { + summary = 'Elegant Lua unit testing.', + detailed = [[ + An elegant, extensible, testing framework. + Ships with a large amount of useful asserts, + plus the ability to write your own. Output + in pretty or plain terminal format, JSON, + or TAP for CI integration. Great for TDD + and unit, integration, and functional tests. + ]], + homepage = 'http://olivinelabs.com/busted/', + license = 'MIT ' +} +dependencies = { + 'lua >= 5.1', + 'lua_cliargs >= 2.0', + 'luafilesystem >= 1.5.0', + 'dkjson >= 2.1.0', + 'say >= 1.2-1', + 'luassert >= 1.7.2-0', + 'ansicolors >= 1.0-1', + 'penlight >= 1.0.0-1', + 'mediator_lua >= 1.1-3', +} +build = { + type = 'builtin', + modules = { + ['busted.core'] = 'busted/core.lua', + ['busted.context'] = 'busted/context.lua', + ['busted.environment'] = 'busted/environment.lua', + ['busted.compatibility'] = 'busted/compatibility.lua', + ['busted.done'] = 'busted/done.lua', + ['busted.status'] = 'busted/status.lua', + ['busted.init'] = 'busted/init.lua', + + ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', + ['busted.modules.luacov'] = 'busted/modules/luacov.lua', + ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', + ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', + + ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', + ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', + ['busted.modules.files.terra'] = 'busted/modules/files/terra.lua', + + ['busted.outputHandlers.base'] = 'busted/outputHandlers/base.lua', + ['busted.outputHandlers.utfTerminal'] = 'busted/outputHandlers/utfTerminal.lua', + ['busted.outputHandlers.plainTerminal'] = 'busted/outputHandlers/plainTerminal.lua', + ['busted.outputHandlers.TAP'] = 'busted/outputHandlers/TAP.lua', + ['busted.outputHandlers.json'] = 'busted/outputHandlers/json.lua', + ['busted.outputHandlers.junit'] = 'busted/outputHandlers/junit.lua', + ['busted.outputHandlers.sound'] = 'busted/outputHandlers/sound.lua', + + ['busted.languages.en'] = 'busted/languages/en.lua', + ['busted.languages.ar'] = 'busted/languages/ar.lua', + ['busted.languages.de'] = 'busted/languages/de.lua', + ['busted.languages.fr'] = 'busted/languages/fr.lua', + ['busted.languages.ja'] = 'busted/languages/ja.lua', + ['busted.languages.nl'] = 'busted/languages/nl.lua', + ['busted.languages.ru'] = 'busted/languages/ru.lua', + ['busted.languages.th'] = 'busted/languages/th.lua', + ['busted.languages.ua'] = 'busted/languages/ua.lua', + ['busted.languages.zh'] = 'busted/languages/zh.lua', + }, + install = { + bin = { + ['busted'] = 'bin/busted' + } + } +} From d2bf4e1577ec30e5cad1cc69ad8b52cb5feb1b0d Mon Sep 17 00:00:00 2001 From: mpeterv Date: Thu, 18 Dec 2014 00:11:18 +0300 Subject: [PATCH 043/293] Be compatible with Lua 5.3 --- busted/compatibility.lua | 4 +++- busted/core.lua | 1 + busted/init.lua | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 12d5bd16..4024ec90 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -25,5 +25,7 @@ return { if name then debug.upvaluejoin(f, up, function() return t end, 1) end - end + end, + + unpack = table.unpack or unpack } diff --git a/busted/core.lua b/busted/core.lua index 4d4e214a..03569422 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -23,6 +23,7 @@ local pendingMt = { local getfenv = require 'busted.compatibility'.getfenv local setfenv = require 'busted.compatibility'.setfenv +local unpack = require 'busted.compatibility'.unpack local throw = error return function() diff --git a/busted/init.lua b/busted/init.lua index f09f97b3..2572c50c 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -1,3 +1,5 @@ +local unpack = require 'busted.compatibility'.unpack + math.randomseed(os.time()) local function shuffle(t, seed) From f97ca48153dd6f7662513dc0e6f55e4242d0d60a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 11 Dec 2014 14:46:50 -0800 Subject: [PATCH 044/293] Create support function globals in parent context When a global is created in a support function (i.e. setup/before_each), create the global in the current block's parent context so that other sibling blocks (i.e. 'it' blocks) can access these globals. Globals created in 'it' blocks are still confined to the current context/test, and not visible to it's siblings. Fixes issues #289 and #302. --- busted/init.lua | 22 +++++++++++++++------- spec/core_spec.lua | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 2572c50c..8ebf6b8b 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -23,15 +23,23 @@ return function(busted) end local function exec(descriptor, element) - if not element.env then element.env = {} end + if not element.env then element.env = {} end - remove({ 'randomize' }, element) - remove({ 'pending' }, element) - remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) - remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) + remove({ 'randomize' }, element) + remove({ 'pending' }, element) + remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) + remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) + + local parent = busted.context.parent(element) + setmetatable(element.env, { + __newindex = function(self, key, value) + if not parent.env then parent.env = {} end + parent.env[key] = value + end + }) - local ret = { busted.safe(descriptor, element.run, element) } - return unpack(ret) + local ret = { busted.safe(descriptor, element.run, element) } + return unpack(ret) end local function execAll(descriptor, current, propagate) diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 70166544..568dc89e 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -231,8 +231,33 @@ end) describe('tests environment', function() global = 'global' + setup(function() + globalsetup = 'globalsetup' + end) + + teardown(function() + globalteardown = 'globalteardown' + end) + + before_each(function() + globalbefore = 'globalbefore' + end) + + after_each(function() + globalafter = 'globalafter' + end) + + it('cannot access globals which have not been created yet', function() + assert.equal(nil, globalafter) + assert.equal(nil, globalteardown) + notglobal = 'notglobal' + end) + it('can access globals', function() assert.equal('global', global) + assert.equal('globalsetup', globalsetup) + assert.equal('globalbefore', globalbefore) + assert.equal('globalafter', globalafter) notglobal = 'notglobal' end) @@ -240,6 +265,15 @@ describe('tests environment', function() assert.equal(nil, notglobal) end) + describe('can access parent globals', function() + it('from child', function() + assert.equal('global', global) + assert.equal('globalsetup', globalsetup) + assert.equal('globalbefore', globalbefore) + assert.equal('globalafter', globalafter) + end) + end) + describe('cannot access globals set in children', function() it('has a global', function() notglobal = 'notglobal' From 1b6fd688c62d53e931d0e6d11f5034066634c083 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 11 Dec 2014 20:45:32 -0800 Subject: [PATCH 045/293] Cleanup suite start/end function signatures The suite start/end published messages do not pass any parameters to their subscribers. Therefore, the subscriber callback functions should not receive any input parameters. --- busted/outputHandlers/TAP.lua | 2 +- busted/outputHandlers/base.lua | 4 ++-- busted/outputHandlers/plainTerminal.lua | 2 +- busted/outputHandlers/sound.lua | 2 +- busted/outputHandlers/utfTerminal.lua | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index c9a8ebcb..f69f3e2a 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -4,7 +4,7 @@ local tablex = require 'pl.tablex' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) - handler.suiteEnd = function(name, parent) + handler.suiteEnd = function() local total = handler.successesCount + handler.errorsCount + handler.failuresCount print('1..' .. total) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 78f9f168..e91997b2 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -67,13 +67,13 @@ return function(busted) return handler.endTime - handler.startTime end - handler.baseSuiteStart = function(name, parent) + handler.baseSuiteStart = function() handler.startTime = os.clock() return nil, true end - handler.baseSuiteEnd = function(name, parent) + handler.baseSuiteEnd = function() handler.endTime = os.clock() return nil, true end diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 7a893b23..06cff1cd 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -128,7 +128,7 @@ return function(options, busted) return nil, true end - handler.suiteEnd = function(name, parent) + handler.suiteEnd = function() print('') print(statusString()) diff --git a/busted/outputHandlers/sound.lua b/busted/outputHandlers/sound.lua index 762090fa..705ae7d1 100644 --- a/busted/outputHandlers/sound.lua +++ b/busted/outputHandlers/sound.lua @@ -4,7 +4,7 @@ return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) local language = require('busted.languages.' .. options.language) - handler.suiteEnd = function(name, parent) + handler.suiteEnd = function() local system, sayer_pre, sayer_post local messages diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index eef64911..238cbcff 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -129,7 +129,7 @@ return function(options, busted) return nil, true end - handler.suiteEnd = function(name, parent) + handler.suiteEnd = function() print('') print(statusString()) From 93507acfb1105a85e403679304066151b577e063 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 11 Dec 2014 20:41:59 -0800 Subject: [PATCH 046/293] Fix issue #283 Run duration is always 0.0 seconds The reported run duration is always 0.0 seconds. This occurs because the terminal output handlers rely on the base output handler to record the start and end times of the suite. However, when the terminal output handler's suiteEnd() function runs, the base output handler's baseSuiteEnd() function has yet to record the end time. Thus, the suite end time is still 'nil' when the terminal output handlers are trying to get the run duration, resulting in a 0 duration. The solution is to ensure that the base output handler subscribes at the highest priority so that the suite end time will be recorded before it is needed by any other output handlers. --- busted/outputHandlers/base.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index e91997b2..a47ce465 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -23,8 +23,8 @@ return function(busted) require('busted.languages.' .. options.language) end - busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart) - busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd) + busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart, { priority = 1 }) + busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd, { priority = 1 }) busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'pending' }, handler.basePending, { predicate = handler.cancelOnPending }) From ac15c1b9b0425754bb4b9501389912b1adad7c38 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 13 Dec 2014 21:29:10 -0800 Subject: [PATCH 047/293] Fix issue #250 Weird context popping At the end of a test suite the last context is popped off the stack leaving it empty. However, this doesn't seem to be intended as there are an equal number of pushes/pops. This error occurs because the context pushes/pops are not done with a stack, but rather relies on the context parent/child relationships. Use a stack to properly keep track of context pushes/pops. --- busted/context.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/busted/context.lua b/busted/context.lua index 315e1c33..979c5e58 100644 --- a/busted/context.lua +++ b/busted/context.lua @@ -4,6 +4,7 @@ return function() local data = {} local parents = {} local children = {} + local stack = {} function context.ref() local ref = {} @@ -21,7 +22,7 @@ return function() function ref.attach(child) if not children[ctx] then children[ctx] = {} end parents[child] = ctx - children[ctx][#children[ctx]+1] = child + table.insert(children[ctx], child) end function ref.children(parent) @@ -32,13 +33,16 @@ return function() return parents[child] end - function ref.push(child) - if not parents[child] then error('Detached child. Cannot push.') end - ctx = child + function ref.push(current) + if not parents[current] then error('Detached child. Cannot push.') end + table.insert(stack, ctx) + ctx = current end function ref.pop() - ctx = parents[ctx] + local current = ctx + ctx = table.remove(stack) + if not ctx then error('Context stack empty. Cannot pop.') end end return ref From a84a34ee88b215054b4f8921bbf8465383e03177 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 13 Dec 2014 21:46:41 -0800 Subject: [PATCH 048/293] Save/Restore global state between test files When a file context is pushed, save a copy of _G and package.loaded. Then when the file context is popped, restore the saved values of _G and package.loaded. This prevents a 'require' in one file from polluting the global environment of another file. This also allows modules that are required in one test file to be reloaded in another test file. This addresses issue #62. --- busted/context.lua | 31 +++++++++++++++++++++++++++++++ spec/file_sandbox1_spec.lua | 14 ++++++++++++++ spec/file_sandbox2_spec.lua | 14 ++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 spec/file_sandbox1_spec.lua create mode 100644 spec/file_sandbox2_spec.lua diff --git a/busted/context.lua b/busted/context.lua index 979c5e58..e4c5d2c0 100644 --- a/busted/context.lua +++ b/busted/context.lua @@ -1,3 +1,27 @@ +local tablex = require 'pl.tablex' + +local function save() + local g = {} + for k,_ in next, _G, nil do + g[k] = rawget(_G, k) + end + return { + gmt = getmetatable(_G), + g = g, + loaded = tablex.copy(package.loaded) + } +end + +local function restore(state) + setmetatable(_G, state.gmt) + for k,_ in next, _G, nil do + rawset(_G, k, state.g[k]) + end + for k,_ in pairs(package.loaded) do + package.loaded[k] = state.loaded[k] + end +end + return function() local context = {} @@ -35,6 +59,9 @@ return function() function ref.push(current) if not parents[current] then error('Detached child. Cannot push.') end + if ctx ~= current and current.descriptor == 'file' then + current.state = save() + end table.insert(stack, ctx) ctx = current end @@ -42,6 +69,10 @@ return function() function ref.pop() local current = ctx ctx = table.remove(stack) + if ctx ~= current and current.state then + restore(current.state) + current.state = nil + end if not ctx then error('Context stack empty. Cannot pop.') end end diff --git a/spec/file_sandbox1_spec.lua b/spec/file_sandbox1_spec.lua new file mode 100644 index 00000000..a6d695fe --- /dev/null +++ b/spec/file_sandbox1_spec.lua @@ -0,0 +1,14 @@ +require 'pl' + +describe('require "pl" in this file', function() + it('loads global environment with "List"', function() + assert.is_not_nil(List) + end) +end) + +describe('require "socket" in another file', function() + it('does not keep "socket" in environment', function() + assert.is_nil(socket) + assert.is_nil(package.loaded.socket) + end) +end) diff --git a/spec/file_sandbox2_spec.lua b/spec/file_sandbox2_spec.lua new file mode 100644 index 00000000..83d99895 --- /dev/null +++ b/spec/file_sandbox2_spec.lua @@ -0,0 +1,14 @@ +socket = require 'socket' + +describe('require "socket" in this file', function() + it('loads environment with "socket"', function() + assert.is_not_nil(socket) + end) +end) + +describe('require "pl" in another file', function() + it('does not keep "List" in environment', function() + assert.is_nil(List) + assert.is_nil(package.loaded['pl.List']) + end) +end) From be6dfd4efd1da76aa1108120db2979e1d093c226 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 14 Dec 2014 01:30:35 -0800 Subject: [PATCH 049/293] Fix issue #272 Syntactic sugar does not work Allow the following alternate syntax for context blocks: describe "something" (function() it "works" (function() assert(true) end) end) --- busted/core.lua | 6 +++++- spec/core_spec.lua | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/busted/core.lua b/busted/core.lua index 03569422..12b26c09 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -165,7 +165,11 @@ return function() trace = busted.getTrace(ctx, 3, name) end - busted.publish({ 'register', descriptor }, name, fn, trace) + local publish = function(f) + busted.publish({ 'register', descriptor }, name, f, trace) + end + + if fn then publish(fn) else return publish end end busted.executors[descriptor] = publisher diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 568dc89e..486ca234 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -283,6 +283,12 @@ describe('tests environment', function() end) end) +describe 'tests syntactic sugar' (function() + it 'works' (function() + assert(true) + end) +end) + describe('tests aliases', function() local test_val = 0 From cdaab739fc41ac49914780b60b36a86496cc9384 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 21 Dec 2014 02:26:26 -0800 Subject: [PATCH 050/293] Fix error message for table error objects When throwing a table as an error, the error message reads 'Nil error', which is confusing because an error object was thrown. The error message should at least display that a table was thrown. Restore the previous behavior of printing out the error table. Issue #284. --- busted/core.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 12b26c09..8139bced 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -135,8 +135,8 @@ return function() local ret = { xpcall(run, function(msg) local errType = metatype(msg) - status = (errType == 'string' and 'error' or errType) - message = busted.rewriteMessage(element, tostring(msg)) + status = ((errType == 'string' or errType == 'table') and 'error' or errType) + message = busted.rewriteMessage(element, errType == 'table' and msg or tostring(msg)) trace = busted.getTrace(element, 3, msg) end) } From 1bc7519c9cc9c548c43d5e3a7eaf3706b7c8c2ed Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 21 Dec 2014 03:36:18 -0800 Subject: [PATCH 051/293] Fix issue #284 Error reporting is inconsistent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Errors are reported differently depending on the type of error message: $ busted testcase_spec.lua ●●● 0 successes / 3 failures / 0 errors / 0 pending : 0.0 seconds Failure → ./testcase_spec.lua @ 10 testcase fails with table error { } Failure → ./testcase_spec.lua @ 6 testcase fails with no error Nil error Failure → ./testcase_spec.lua @ 2 testcase fails with string error ./testcase_spec.lua:3: error message Update error reporting to display the file and line information for non-string error types. So the above now displays as the following: $ busted testcase_spec.lua ●●● 0 successes / 3 failures / 0 errors / 0 pending : 0.0 seconds Failure → ./testcase_spec.lua @ 10 testcase fails with table error ./testcase_spec.lua:11: { } Failure → ./testcase_spec.lua @ 6 testcase fails with no error ./testcase_spec.lua:7: Nil error Failure → ./testcase_spec.lua @ 2 testcase fails with string error ./testcase_spec.lua:3: error message --- busted/core.lua | 14 +++++++++++--- spec/cl_error_messages.lua | 15 +++++++++++++++ spec/cl_spec.lua | 18 ++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 spec/cl_error_messages.lua diff --git a/busted/core.lua b/busted/core.lua index 8139bced..7da30536 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -24,6 +24,7 @@ local pendingMt = { local getfenv = require 'busted.compatibility'.getfenv local setfenv = require 'busted.compatibility'.setfenv local unpack = require 'busted.compatibility'.unpack +local pretty = require 'pl.pretty' local throw = error return function() @@ -59,8 +60,15 @@ return function() return file.getTrace(file.name, info) end - busted.rewriteMessage = function(element, message) + busted.rewriteMessage = function(element, message, trace) local file = busted.getFile(element) + if getmetatable(message) and getmetatable(message).__tostring then + message = tostring(message) + elseif type(message) ~= 'string' then + local trace = trace or busted.getTrace(element, 3, message) + local fileline = trace.short_src .. ':' .. trace.currentline .. ': ' + message = fileline .. (message and pretty.write(message) or 'Nil error') + end return file.rewriteMessage and file.rewriteMessage(file.name, message) or message end @@ -135,9 +143,9 @@ return function() local ret = { xpcall(run, function(msg) local errType = metatype(msg) - status = ((errType == 'string' or errType == 'table') and 'error' or errType) - message = busted.rewriteMessage(element, errType == 'table' and msg or tostring(msg)) + status = ((errType == 'pending' or errType == 'failure') and errType or 'error') trace = busted.getTrace(element, 3, msg) + message = busted.rewriteMessage(element, msg, trace) end) } if not ret[1] then diff --git a/spec/cl_error_messages.lua b/spec/cl_error_messages.lua new file mode 100644 index 00000000..4eda92ed --- /dev/null +++ b/spec/cl_error_messages.lua @@ -0,0 +1,15 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Test error messages show file and line for', function() + it('table errors #table', function() + error({}) + end) + + it('nil errors #nil', function() + error() + end) + + it('string errors #string', function() + error('error message') + end) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 121a8f87..a20c7dee 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -259,6 +259,24 @@ describe('Tests error messages through the command line', function() error_end() end) + it('when throwning an error table', function() + error_start() + local result = run('bin/busted --output=plainTerminal --tags=table --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%./spec/.-)\n') + local expected = './spec/cl_error_messages.lua:5: {' + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when throwning a nil error', function() + error_start() + local result = run('bin/busted --output=plainTerminal --tags=nil --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%./spec/.-)\n') + local expected = './spec/cl_error_messages.lua:9: Nil error' + assert.is_equal(expected, errmsg) + error_end() + end) + it('when running a non-compiling testfile', function() error_start() local result = run('bin/busted --output=plainTerminal --pattern=cl_compile_fail.lua$') From c546df679b7ac00a44d676834fab3396d6756370 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 24 Dec 2014 00:44:27 -0800 Subject: [PATCH 052/293] Issue #284 Refactor error reporting Refactor error reporting to have Lua insert file and line into the error message. --- busted/core.lua | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 7da30536..43c6cf65 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -1,4 +1,4 @@ -local metatype = function(obj) +local function metatype(obj) local otype = type(obj) if otype == 'table' then local mt = getmetatable(obj) @@ -43,7 +43,7 @@ return function() busted.status = require 'busted.status' - busted.getTrace = function(element, level, msg) + function busted.getTrace(element, level, msg) level = level or 3 local info = debug.getinfo(level, 'Sl') @@ -60,16 +60,19 @@ return function() return file.getTrace(file.name, info) end - busted.rewriteMessage = function(element, message, trace) - local file = busted.getFile(element) - if getmetatable(message) and getmetatable(message).__tostring then - message = tostring(message) - elseif type(message) ~= 'string' then - local trace = trace or busted.getTrace(element, 3, message) - local fileline = trace.short_src .. ':' .. trace.currentline .. ': ' - message = fileline .. (message and pretty.write(message) or 'Nil error') + function busted.getErrorMessage(err) + if getmetatable(err) and getmetatable(err).__tostring then + return tostring(err) + elseif type(err) ~= 'string' then + return err and pretty.write(err) or 'Nil error' end + return err + end + + function busted.rewriteMessage(element, message, trace) + local file = busted.getFile(element) + return file.rewriteMessage and file.rewriteMessage(file.name, message) or message end @@ -109,7 +112,7 @@ return function() end function busted.fail(msg, level) - local _, emsg = pcall(error, msg, level+2) + local _, emsg = pcall(throw, msg, level+2) local e = { message = emsg } setmetatable(e, failureMt) throw(e, level+1) @@ -141,11 +144,19 @@ return function() local trace, message local status = 'success' + if not element.env then element.env = {} end + + element.env.error = function(msg, level) + local level = level or 1 + _, message = pcall(throw, busted.getErrorMessage(msg), level+2) + error(msg, level+1) + end + local ret = { xpcall(run, function(msg) local errType = metatype(msg) status = ((errType == 'pending' or errType == 'failure') and errType or 'error') trace = busted.getTrace(element, 3, msg) - message = busted.rewriteMessage(element, msg, trace) + message = busted.rewriteMessage(element, message or tostring(msg), trace) end) } if not ret[1] then From 4f9f0a53f3ffbe7f43f10da2732b394d6685ac88 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 21 Dec 2014 23:58:59 -0800 Subject: [PATCH 053/293] Fix getfenv/setfenv for Lua 5.2 compatibility It is possible for getfenv to return nil for a function with no globals. Use unique upvalue for setfenv. --- busted/compatibility.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 4024ec90..78caf36e 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -9,7 +9,7 @@ return { name, value = debug.getupvalue(f, up) until name == '_ENV' or name == nil - return (name and value or _G) + return value end, setfenv = setfenv or function(f, t) @@ -23,8 +23,11 @@ return { until name == '_ENV' or name == nil if name then - debug.upvaluejoin(f, up, function() return t end, 1) + debug.upvaluejoin(f, up, function() return name end, 1) + debug.setupvalue(f, up, t) end + + if f ~= 0 then return f end end, unpack = table.unpack or unpack From 4a8d029d7152bf526e8a1a82032c466b60cdd3b8 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 23 Dec 2014 01:39:06 -0800 Subject: [PATCH 054/293] Fix issue #313 Failure line numbers in moonscript Fix moonscript file loader - Fix error message parsing and rewriting - Fix traceback parsing and rewriting - Fix file line number lookup - Fix error message for file loading errors --- busted/modules/files/moonscript.lua | 56 +++++++++++++------------- spec/cl_moonscript_error_messages.moon | 22 ++++++++++ spec/cl_spec.lua | 44 ++++++++++++++++++++ 3 files changed, 95 insertions(+), 27 deletions(-) create mode 100644 spec/cl_moonscript_error_messages.moon diff --git a/busted/modules/files/moonscript.lua b/busted/modules/files/moonscript.lua index 497a5fbb..acd0219d 100644 --- a/busted/modules/files/moonscript.lua +++ b/busted/modules/files/moonscript.lua @@ -18,7 +18,7 @@ local lookup_line = function(fname, pos) end local rewrite_linenumber = function(fname, lineno) - local tbl = line_tables[fname] + local tbl = line_tables['@' .. fname] if fname and tbl then for i = lineno, 0 ,-1 do if tbl[i] then @@ -30,44 +30,49 @@ local rewrite_linenumber = function(fname, lineno) return lineno end -local rewrite_traceback = function(fname, trace) - local lines = {} - local j = 0 +local rewrite_filename = function(filename) + -- sometimes moonscript gives files like [string "./filename.moon"], so + -- we'll chop it up to only get the filename. + return filename:match('string "(.+)"') or filename +end - local rewrite_one = function(line) - if line == nil then - return '' - end +local rewrite_traceback = function(fname, trace) + local rewrite_one = function(line, pattern, sub) + if line == nil then return '' end - local fname, lineno = line:match('[^"]+"([^:]+)".:(%d+):') + local fname, lineno = line:match(pattern) if fname and lineno then + fname = rewrite_filename(fname) local new_lineno = rewrite_linenumber(fname, tonumber(lineno)) if new_lineno then - line = line:gsub(':' .. lineno .. ':', ':' .. new_lineno .. ':') + line = line:gsub(sub:format(tonumber(lineno)), sub:format(tonumber(new_lineno))) end end + return line end + local lines = {} + local j = 0 + for line in trace:gmatch('[^\r\n]+') do j = j + 1 - lines[j] = rewrite_one(line) + line = rewrite_one(line, '%s*(.-):(%d+): ', ':%d:') + line = rewrite_one(line, '<(.*):(%d+)>', ':%d>') + lines[j] = line end - return table.concat(lines, trace:match('[\r\n]+')) + return '\n' .. table.concat(lines, trace:match('[\r\n]+')) .. '\n' end local ret = {} local getTrace = function(filename, info) - local p = require 'pl.pretty' local index = info.traceback:find('\n%s*%[C]') info.traceback = info.traceback:sub(1, index) - -- sometimes moonscript gives files like [string "./filename.moon"], so - -- we'll chop it up to only get the filename. - info.short_src = info.short_src:match('string "(.+)"') or info.short_src + info.short_src = rewrite_filename(info.short_src) info.traceback = rewrite_traceback(filename, info.traceback) info.linedefined = rewrite_linenumber(filename, info.linedefined) info.currentline = rewrite_linenumber(filename, info.currentline) @@ -76,19 +81,15 @@ local getTrace = function(filename, info) end local rewriteMessage = function(filename, message) - local split = utils.split(message, ':', true, 3) - - if #split < 3 then + local fname, line, msg = message:match('(.-):(%d+): (.*)') + if not fname then return message end - local filename = split[1] - local line = split[2] - filename = filename:match('string "(.+)"') - - line = rewrite_linenumber(filename, line) + fname = rewrite_filename(fname) + line = rewrite_linenumber(fname, tonumber(line)) - return filename .. ':' .. tostring(line) + return fname .. ':' .. tostring(line) .. ': ' .. msg end ret.match = function(busted, filename) @@ -104,15 +105,16 @@ ret.load = function(busted, filename) local file local success, err = pcall(function() + local err file, err = moonscript.loadfile(filename) if not file then - busted.publish({ 'error', 'file' }, filename, nil, nil, err) + busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) end end) if not success then - busted.publish({ 'error', 'file' }, filename, nil, nil, err) + busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) end return file, getTrace, rewriteMessage diff --git a/spec/cl_moonscript_error_messages.moon b/spec/cl_moonscript_error_messages.moon new file mode 100644 index 00000000..3dcb3ea7 --- /dev/null +++ b/spec/cl_moonscript_error_messages.moon @@ -0,0 +1,22 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe 'Test moonscript errors show file and line for', -> + it 'failures #fail', -> + assert.is_equal true, false + return + + it 'table errors #table', -> + error {} + return + + it 'nil errors #nil', -> + error! + return + + it 'string errors #string', -> + error 'error message' + return + + return + +return diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index a20c7dee..90df2028 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -317,6 +317,50 @@ describe('Tests error messages through the command line', function() end) end) +describe('Tests moonscript error messages through the command line', function() + it('when assertion fails', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') + local err = result:match('(Failure → .-)\n') + local errmsg = result:match('\n(%./spec/.-)\n') + local expectedErr = "Failure → ./spec/cl_moonscript_error_messages.moon @ 4" + local expectedMsg = "./spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." + assert.is_equal(expectedErr, err) + assert.is_equal(expectedMsg, errmsg) + error_end() + end) + + it('when throwing string errors', function() + error_start() + local result = run('bin/busted --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') + local err = result:match('(Error → .-)\n') + local errmsg = result:match('\n(%./spec/.-)\n') + local expectedErr = "Error → ./spec/cl_moonscript_error_messages.moon @ 16" + local expectedMsg = "./spec/cl_moonscript_error_messages.moon:17: error message" + assert.is_equal(expectedErr, err) + assert.is_equal(expectedMsg, errmsg) + error_end() + end) + + it('when throwning an error table', function() + error_start() + local result = run('bin/busted --output=plainTerminal --tags=table --pattern=cl_moonscript_error_messages.moon$') + local errmsg = result:match('\n(%./spec/.-)\n') + local expected = './spec/cl_moonscript_error_messages.moon:9: {' + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when throwning a nil error', function() + error_start() + local result = run('bin/busted --output=plainTerminal --tags=nil --pattern=cl_moonscript_error_messages.moon$') + local errmsg = result:match('\n(%./spec/.-)\n') + local expected = './spec/cl_moonscript_error_messages.moon:13: Nil error' + assert.is_equal(expected, errmsg) + error_end() + end) +end) + describe('Tests pending through the commandline', function() it('skips tests inside pending scope', function() local success, exitcode From dec09bf5f31ada7b8bef852d55988a99ec34d8b6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 24 Dec 2014 23:22:35 -0800 Subject: [PATCH 055/293] Fix error message for terra test files --- busted/modules/files/terra.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/modules/files/terra.lua b/busted/modules/files/terra.lua index 62e9265e..ea485235 100644 --- a/busted/modules/files/terra.lua +++ b/busted/modules/files/terra.lua @@ -24,12 +24,12 @@ ret.load = function(busted, filename) file, err = terralib.loadfile(filename) if not file then - busted.publish({ 'error', 'file' }, filename, nil, nil, err) + busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) end end) if not success then - busted.publish({ 'error', 'file' }, filename, nil, nil, err) + busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) end return file, getTrace From e5745e39746afb125d86d73d720f4aeaa1e906f6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 23 Dec 2014 01:53:22 -0800 Subject: [PATCH 056/293] Remove unnecessary tail call Remove tail call in busted.execute() so that the stack trace shows more information. The function passed to busted.safe() does not need to return anything, so just remove the 'return' keyword. --- busted/core.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/core.lua b/busted/core.lua index 43c6cf65..39b967b1 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -220,7 +220,7 @@ return function() for _, v in pairs(busted.context.children(current)) do local executor = executors[v.descriptor] if executor then - busted.safe(v.descriptor, function() return executor(v) end, v) + busted.safe(v.descriptor, function() executor(v) end, v) end end end From 3ec4615d31c00e04e118f2ae455b74568d01c851 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 13 Dec 2014 22:17:00 -0800 Subject: [PATCH 057/293] Remove unnecessary requires in output handlers --- busted/outputHandlers/TAP.lua | 1 - busted/outputHandlers/json.lua | 1 - 2 files changed, 2 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index f69f3e2a..ebec4677 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -1,5 +1,4 @@ local pretty = require 'pl.pretty' -local tablex = require 'pl.tablex' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) diff --git a/busted/outputHandlers/json.lua b/busted/outputHandlers/json.lua index d315efa4..185d3c30 100644 --- a/busted/outputHandlers/json.lua +++ b/busted/outputHandlers/json.lua @@ -1,5 +1,4 @@ local pretty = require 'pl.pretty' -local tablex = require 'pl.tablex' local json = require 'dkjson' return function(options, busted) From de99b214c4c135821ca2230e21e836a866a58e37 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 13 Dec 2014 22:19:18 -0800 Subject: [PATCH 058/293] Display error dots on file/describe failure --- busted/outputHandlers/plainTerminal.lua | 2 ++ busted/outputHandlers/utfTerminal.lua | 2 ++ 2 files changed, 4 insertions(+) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 06cff1cd..6c48a82e 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -160,7 +160,9 @@ return function(options, busted) busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) + busted.subscribe({ 'failure', 'file' }, handler.error) busted.subscribe({ 'error', 'describe' }, handler.error) + busted.subscribe({ 'failure', 'describe' }, handler.error) return handler end diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 238cbcff..44451aa0 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -161,7 +161,9 @@ return function(options, busted) busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) + busted.subscribe({ 'failure', 'file' }, handler.error) busted.subscribe({ 'error', 'describe' }, handler.error) + busted.subscribe({ 'failure', 'describe' }, handler.error) return handler end From a0a8d6e6610044b85160e56225c72f50d79611a4 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 13 Dec 2014 22:23:53 -0800 Subject: [PATCH 059/293] Fix junit output for file errors --- busted/outputHandlers/junit.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index c11df0db..9c78c54a 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -51,12 +51,11 @@ return function(options, busted) return nil, true end - handler.errorFile = function() - if status == 'failure' then - xml_doc.attr.errors = xml_doc.attr.errors + 1 - end - - xml_doc:addtag('failure', {}):text(trace.traceback):up() + handler.errorFile = function(element, parent, message, trace) + xml_doc.attr.errors = xml_doc.attr.errors + 1 + xml_doc:addtag('error') + xml_doc:text(trace.traceback) + xml_doc:up() return nil, true end @@ -65,6 +64,7 @@ return function(options, busted) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'error', 'file' }, handler.errorFile) + busted.subscribe({ 'failure', 'file' }, handler.errorFile) return handler end From dc532363b9008679c6d9a4de328e6cf53cf2c405 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 20 Dec 2014 23:41:51 -0800 Subject: [PATCH 060/293] Fix TAP output to show errors TAP output was only showing success and failure results, but not errors. So update TAP output to show errors as "not ok", just like failures. --- busted/outputHandlers/TAP.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index ebec4677..d6efb4fe 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -16,7 +16,7 @@ return function(options, busted) print( success:format( counter, t.name )) end - for i,t in pairs(handler.failures) do + showFailure = function(t) counter = counter + 1 local message = t.message @@ -31,6 +31,13 @@ return function(options, busted) print('# Failure message: ' .. message:gsub('\n', '\n# ' )) end + for i,t in pairs(handler.errors) do + showFailure(t) + end + for i,t in pairs(handler.failures) do + showFailure(t) + end + return nil, true end From 8e48e0c5927f8d64b3280666124225ca92609c3e Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 21 Dec 2014 01:50:05 -0800 Subject: [PATCH 061/293] Fix tests not running in parent directories Error in pl.path.normpath causes leading '../' directories to be stripped from a file path. This, in turn, prevents busted from finding any files located in parent/ancestor directories. Implement a fixed version of normpath and use it instead of pl.path.normpath. --- bin/busted | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/bin/busted b/bin/busted index 7e22259d..6b7f3606 100755 --- a/bin/busted +++ b/bin/busted @@ -12,6 +12,39 @@ local luacov = require 'busted.modules.luacov'() local path = require 'pl.path' local utils = require 'pl.utils' +-- Do not use pl.path.normpath +-- It is broken for paths with leading '../../' +local function normpath(fpath) + if type(fpath) ~= 'string' then + error(fpath .. ' is not a string') + end + local sep = '/' + if path.is_windows then + sep = '\\' + if fpath:match '^\\\\' then -- UNC + return '\\\\' .. normpath(fpath:sub(3)) + end + fpath = fpath:gsub('/','\\') + end + local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' + local np_pat1 = np_gen1:gsub('SEP', sep) + local np_pat2 = np_gen2:gsub('SEP', sep) + local k + repeat -- /./ -> / + fpath, k = fpath:gsub(np_pat2, sep) + until k == 0 + repeat -- A/../ -> (empty) + local oldpath = fpath + fpath, k = fpath:gsub(np_pat1, function(d, up) + if d == '..' then return nil end + if d == '.' then return up end + return '' + end) + until k == 0 or oldpath == fpath + if fpath == '' then fpath = '.' end + return fpath +end + require 'busted.init'(busted) -- Default cli arg values @@ -64,7 +97,7 @@ local fpath = cliArgs.d -- Load busted config file if available local configFile = { } -local bustedConfigFilePath = path.normpath(path.join(fpath, '.busted')) +local bustedConfigFilePath = normpath(path.join(fpath, '.busted')) local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) @@ -79,7 +112,7 @@ if bustedConfigFile then end -- Load test directory -local rootFile = path.normpath(path.join(fpath, cliArgs.ROOT)) +local rootFile = normpath(path.join(fpath, cliArgs.ROOT)) local tags = {} local excludeTags = {} From 769bbe3c9c6a6fc75d78ef7ae53a1b8af58f5292 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 17 Dec 2014 21:59:52 -0800 Subject: [PATCH 062/293] Fix help string for the default seed value --- bin/busted | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/bin/busted b/bin/busted index 6b7f3606..61bdde98 100755 --- a/bin/busted +++ b/bin/busted @@ -51,7 +51,7 @@ require 'busted.init'(busted) local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' local defaultLoaders = 'lua,moonscript' local defaultPattern = '_spec' -local defaultSeed = tostring(os.time()) +local defaultSeed = 'os.time()' local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' @@ -190,12 +190,9 @@ end) -- Set up randomization options busted.randomize = cliArgs.randomize -local randomseed = tonumber(cliArgs.seed) -if randomseed then - busted.randomseed = randomseed -else +busted.randomseed = tonumber(cliArgs.seed) or os.time() +if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then print('Argument to --seed must be a number') - busted.randomseed = defaultSeed errors = errors + 1 end From b6184c4b02f5aaa48a57fcc6a4bc6c5cae1bcfa4 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 14 Dec 2014 23:28:58 -0800 Subject: [PATCH 063/293] Add shuffle commandline flag (alias for randomize) --- bin/busted | 5 +++-- spec/cl_spec.lua | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/bin/busted b/bin/busted index 61bdde98..648b20bd 100755 --- a/bin/busted +++ b/bin/busted @@ -69,7 +69,7 @@ cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) cli:add_option('-r, --run=RUN', 'config to run from .busted file') -cli:add_option('--seed=SEED', 'random seed value to use for randomizing test order', defaultSeed) +cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed) cli:add_option('--lang=LANG', 'language for error messages', 'en') cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) cli:add_option('--helper=PATH', 'A helper script that is run before tests') @@ -78,6 +78,7 @@ cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to cli:add_flag('-v, --verbose', 'verbose output of errors') cli:add_flag('-s, --enable-sound', 'executes `say` command if available') cli:add_flag('--randomize', 'force randomized test order') +cli:add_flag('--shuffle', 'force randomized test order (alias for randomize)') cli:add_flag('--suppress-pending', 'suppress `pending` test output') cli:add_flag('--defer-print', 'defer print to when test suite is complete') @@ -189,7 +190,7 @@ busted.subscribe({ 'failure' }, function(element, parent, status) end) -- Set up randomization options -busted.randomize = cliArgs.randomize +busted.randomize = cliArgs.randomize or cliArgs.shuffle busted.randomseed = tonumber(cliArgs.seed) or os.time() if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then print('Argument to --seed must be a number') diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 90df2028..b632374a 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -430,7 +430,16 @@ describe('Tests random seed through the commandline', function() end) end) -describe('Tests randomize commandline option', function() +describe('Tests randomize/shuffle commandline option', function() + it('forces test shuffling for non-randomized tests', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --shuffle --pattern=cl_randomize.lua$') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) + it('forces test randomization for non-randomized tests', function() local success, exitcode error_start() From ea619bdebeb280fd84096ebd5ac36b033fae5ac7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 14 Dec 2014 23:21:13 -0800 Subject: [PATCH 064/293] Add commandline option to repeat tests --- bin/busted | 39 +++++++++++++++++++++++++++++++--- busted/context.lua | 8 +++++++ busted/outputHandlers/base.lua | 14 ++++++++++++ spec/cl_spec.lua | 11 ++++++++++ 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/bin/busted b/bin/busted index 648b20bd..dbc434fe 100755 --- a/bin/busted +++ b/bin/busted @@ -69,6 +69,7 @@ cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) cli:add_option('-r, --run=RUN', 'config to run from .busted file') +cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1') cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed) cli:add_option('--lang=LANG', 'language for error messages', 'en') cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) @@ -247,9 +248,41 @@ if #fileList == 0 then errors = errors + 1 end -busted.publish({ 'suite', 'start' }) -busted.execute() -busted.publish({ 'suite', 'end' }) +busted.subscribe({'suite', 'repeat'}, function() + local oldctx = busted.context.get() + local children = busted.context.children(oldctx) + + busted.context.clear() + local ctx = busted.context.get() + for k, v in pairs(oldctx) do + ctx[k] = v + end + + for _, child in pairs(children) do + for descriptor, _ in pairs(busted.executors) do + child[descriptor] = nil + end + busted.context.attach(child) + end + + busted.randomseed = tonumber(cliArgs.seed) or os.time() + + return nil, true +end) + +local runs = tonumber(cliArgs['repeat']) or 1 +local runString = (runs > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') +for i = 1, runs do + io.write(runString:format(i, runs)) + io.flush() + if i > 1 then + busted.publish({ 'suite', 'repeat' }) + end + + busted.publish({ 'suite', 'start' }) + busted.execute() + busted.publish({ 'suite', 'end' }) +end local exit = 0 if failures > 0 or errors > 0 then diff --git a/busted/context.lua b/busted/context.lua index e4c5d2c0..4cf0f3b5 100644 --- a/busted/context.lua +++ b/busted/context.lua @@ -43,6 +43,14 @@ return function() ctx[key] = value end + function ref.clear() + data = {} + parents = {} + children = {} + stack = {} + ctx = data + end + function ref.attach(child) if not children[ctx] then children[ctx] = {} end parents[child] = ctx diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index a47ce465..75e0a147 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -23,6 +23,7 @@ return function(busted) require('busted.languages.' .. options.language) end + busted.subscribe({ 'suite', 'repeat' }, handler.baseSuiteRepeat, { priority = 1 }) busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart, { priority = 1 }) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd, { priority = 1 }) busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) @@ -69,6 +70,19 @@ return function(busted) handler.baseSuiteStart = function() handler.startTime = os.clock() + return nil, true + end + + handler.baseSuiteRepeat = function() + handler.successes = {} + handler.successesCount = 0 + handler.pendings = {} + handler.pendingsCount = 0 + handler.failures = {} + handler.failuresCount = 0 + handler.errors = {} + handler.errorsCount = 0 + handler.inProgress = {} return nil, true end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index b632374a..8b08a8b3 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -449,3 +449,14 @@ describe('Tests randomize/shuffle commandline option', function() error_end() end) end) + +describe('Tests repeat commandline option', function() + it('forces tests to repeat n times', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --repeat=2 --pattern=cl_two_failures.lua$') + assert.is_false(success) + assert.is_equal(4, exitcode) + error_end() + end) +end) From 150288c7617d4199b759a61b7ac0b26a0ec6bbc0 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 16 Dec 2014 22:27:04 -0800 Subject: [PATCH 065/293] Support running tests standalone Allow unit tests to be run standalone by just adding a require to the top of a test file. This is useful if, for some reason, a command line tool is not viable. Just add the following require statement to the beginning of a test file: require 'busted.runner'() When the require is present, the test file can be run standalone or with the busted command line tool. This addresses issue #294. --- bin/busted | 293 +----------------------------------- busted-2.0.rc4-0.rockspec | 1 + busted/runner.lua | 307 ++++++++++++++++++++++++++++++++++++++ spec/cl_spec.lua | 72 +++++++++ spec/cl_standalone.lua | 29 ++++ 5 files changed, 410 insertions(+), 292 deletions(-) create mode 100644 busted/runner.lua create mode 100644 spec/cl_standalone.lua diff --git a/bin/busted b/bin/busted index dbc434fe..1184902c 100755 --- a/bin/busted +++ b/bin/busted @@ -1,294 +1,3 @@ #!/usr/bin/env lua -- Busted command-line runner - -local cli = require 'cliargs' -local busted = require 'busted.core'() - -local configLoader = require 'busted.modules.configuration_loader'() -local outputHandlerLoader = require 'busted.modules.output_handler_loader'() - -local luacov = require 'busted.modules.luacov'() - -local path = require 'pl.path' -local utils = require 'pl.utils' - --- Do not use pl.path.normpath --- It is broken for paths with leading '../../' -local function normpath(fpath) - if type(fpath) ~= 'string' then - error(fpath .. ' is not a string') - end - local sep = '/' - if path.is_windows then - sep = '\\' - if fpath:match '^\\\\' then -- UNC - return '\\\\' .. normpath(fpath:sub(3)) - end - fpath = fpath:gsub('/','\\') - end - local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' - local np_pat1 = np_gen1:gsub('SEP', sep) - local np_pat2 = np_gen2:gsub('SEP', sep) - local k - repeat -- /./ -> / - fpath, k = fpath:gsub(np_pat2, sep) - until k == 0 - repeat -- A/../ -> (empty) - local oldpath = fpath - fpath, k = fpath:gsub(np_pat1, function(d, up) - if d == '..' then return nil end - if d == '.' then return up end - return '' - end) - until k == 0 or oldpath == fpath - if fpath == '' then fpath = '.' end - return fpath -end - -require 'busted.init'(busted) - --- Default cli arg values -local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' -local defaultLoaders = 'lua,moonscript' -local defaultPattern = '_spec' -local defaultSeed = 'os.time()' -local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' -local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - --- Load up the command-line interface options -cli:set_name('busted') -cli:add_flag('--version', 'prints the program version and exits') - -cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1) - -cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput) -cli:add_option('-d, --cwd=cwd', 'path to current working directory', './') -cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern) -cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags') -cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags') -cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) -cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) -cli:add_option('-r, --run=RUN', 'config to run from .busted file') -cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1') -cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed) -cli:add_option('--lang=LANG', 'language for error messages', 'en') -cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) -cli:add_option('--helper=PATH', 'A helper script that is run before tests') - -cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') -cli:add_flag('-v, --verbose', 'verbose output of errors') -cli:add_flag('-s, --enable-sound', 'executes `say` command if available') -cli:add_flag('--randomize', 'force randomized test order') -cli:add_flag('--shuffle', 'force randomized test order (alias for randomize)') -cli:add_flag('--suppress-pending', 'suppress `pending` test output') -cli:add_flag('--defer-print', 'defer print to when test suite is complete') - --- Parse the cli arguments -local cliArgs, hasError = cli:parse() -if hasError then - os.exit(1) -end - --- Return early if only asked for the version -if cliArgs.version then - return print(busted.version) -end - --- Load current working directory -local fpath = cliArgs.d - --- Load busted config file if available -local configFile = { } -local bustedConfigFilePath = normpath(path.join(fpath, '.busted')) - -local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) - -if bustedConfigFile then - local config, err = configLoader(configFile, cliArgs) - - if err then - print(err) - else - cliArgs = config - end -end - --- Load test directory -local rootFile = normpath(path.join(fpath, cliArgs.ROOT)) - -local tags = {} -local excludeTags = {} - -if cliArgs.t ~= '' then - tags = utils.split(cliArgs.t, ',') -end - -if cliArgs['exclude-tags'] ~= '' then - excludeTags = utils.split(cliArgs['exclude-tags'], ',') -end - --- If coverage arg is passed in, load LuaCovsupport -if cliArgs.coverage then - luacov() -end - --- Add additional package paths based on lpath and cpath cliArgs -if #cliArgs.lpath > 0 then - lpathprefix = cliArgs.lpath - lpathprefix = lpathprefix:gsub('^%.[/%\\]', fpath ) - lpathprefix = lpathprefix:gsub(';%.[/%\\]', ';' .. fpath) - package.path = (lpathprefix .. ';' .. package.path):gsub(';;',';') -end - -if #cliArgs.cpath > 0 then - cpathprefix = cliArgs.cpath - cpathprefix = cpathprefix:gsub('^%.[/%\\]', fpath ) - cpathprefix = cpathprefix:gsub(';%.[/%\\]', ';' .. fpath) - package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') -end - -if cliArgs.helper ~= '' then - dofile(cliArgs.helper) -end - -local loaders = {} -if #cliArgs.loaders > 0 then - string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) -end - --- We report an error if the same tag appears in both `options.tags` --- and `options.excluded_tags` because it does not make sense for the --- user to tell Busted to include and exclude the same tests at the --- same time. -for _, excluded in pairs(excludeTags) do - for _, included in pairs(tags) do - if excluded == included then - print('Cannot use --tags and --exclude-tags for the same tags') - os.exit(1) - end - end -end - --- watch for test errors -local failures = 0 -local errors = 0 - -busted.subscribe({ 'error' }, function(element, parent, status) - if element.descriptor == 'output' then - print('Cannot load output library: ' .. element.name) - end - errors = errors + 1 - return nil, true -end) - -busted.subscribe({ 'failure' }, function(element, parent, status) - if element.descriptor == 'it' then - failures = failures + 1 - else - errors = errors + 1 - end - return nil, true -end) - --- Set up randomization options -busted.randomize = cliArgs.randomize or cliArgs.shuffle -busted.randomseed = tonumber(cliArgs.seed) or os.time() -if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then - print('Argument to --seed must be a number') - errors = errors + 1 -end - --- Set up output handler to listen to events -local outputHandlerOptions = { - verbose = cliArgs.verbose, - suppressPending = cliArgs['suppress-pending'], - language = cliArgs.lang, - deferPrint = cliArgs['defer-print'] -} - -local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted, defaultOutput) -outputHandler:subscribe(outputHandlerOptions) - -if cliArgs.s then - require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) -end - -local hasTag = function(name, tag) - local found = name:find('#' .. tag) - return (found ~= nil) -end - -local checkTags = function(name) - for i, tag in pairs(excludeTags) do - if hasTag(name, tag) then - return nil, false - end - end - - for i, tag in pairs(tags) do - if hasTag(name, tag) then - return nil, true - end - end - - return nil, (#tags == 0) -end - -if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then - -- Watch for tags - busted.subscribe({ 'register', 'it' }, checkTags, { priority = 1 }) - busted.subscribe({ 'register', 'pending' }, checkTags, { priority = 1 }) -end - -local pattern = cliArgs.pattern -local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) -local fileList = testFileLoader(rootFile, pattern) -if #fileList == 0 then - print('No test files found matching Lua pattern: ' .. pattern) - errors = errors + 1 -end - -busted.subscribe({'suite', 'repeat'}, function() - local oldctx = busted.context.get() - local children = busted.context.children(oldctx) - - busted.context.clear() - local ctx = busted.context.get() - for k, v in pairs(oldctx) do - ctx[k] = v - end - - for _, child in pairs(children) do - for descriptor, _ in pairs(busted.executors) do - child[descriptor] = nil - end - busted.context.attach(child) - end - - busted.randomseed = tonumber(cliArgs.seed) or os.time() - - return nil, true -end) - -local runs = tonumber(cliArgs['repeat']) or 1 -local runString = (runs > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') -for i = 1, runs do - io.write(runString:format(i, runs)) - io.flush() - if i > 1 then - busted.publish({ 'suite', 'repeat' }) - end - - busted.publish({ 'suite', 'start' }) - busted.execute() - busted.publish({ 'suite', 'end' }) -end - -local exit = 0 -if failures > 0 or errors > 0 then - exit = failures + errors - if exit > 255 then - exit = 255 - end -end -os.exit(exit) +require 'busted.runner'({ batch = true }) diff --git a/busted-2.0.rc4-0.rockspec b/busted-2.0.rc4-0.rockspec index f51fd056..c56484c9 100644 --- a/busted-2.0.rc4-0.rockspec +++ b/busted-2.0.rc4-0.rockspec @@ -36,6 +36,7 @@ build = { ['busted.environment'] = 'busted/environment.lua', ['busted.compatibility'] = 'busted/compatibility.lua', ['busted.done'] = 'busted/done.lua', + ['busted.runner'] = 'busted/runner.lua', ['busted.status'] = 'busted/status.lua', ['busted.init'] = 'busted/init.lua', diff --git a/busted/runner.lua b/busted/runner.lua new file mode 100644 index 00000000..080c4468 --- /dev/null +++ b/busted/runner.lua @@ -0,0 +1,307 @@ +-- Busted command-line runner + +local path = require 'pl.path' +local utils = require 'pl.utils' +local loaded = false + +-- Do not use pl.path.normpath +-- It is broken for paths with leading '../../' +local function normpath(fpath) + if type(fpath) ~= 'string' then + error(fpath .. ' is not a string') + end + local sep = '/' + if path.is_windows then + sep = '\\' + if fpath:match '^\\\\' then -- UNC + return '\\\\' .. normpath(fpath:sub(3)) + end + fpath = fpath:gsub('/','\\') + end + local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' + local np_pat1 = np_gen1:gsub('SEP', sep) + local np_pat2 = np_gen2:gsub('SEP', sep) + local k + repeat -- /./ -> / + fpath, k = fpath:gsub(np_pat2, sep) + until k == 0 + repeat -- A/../ -> (empty) + local oldpath = fpath + fpath, k = fpath:gsub(np_pat1, function(d, up) + if d == '..' then return nil end + if d == '.' then return up end + return '' + end) + until k == 0 or oldpath == fpath + if fpath == '' then fpath = '.' end + return fpath +end + +return function(options) + +if loaded then return else loaded = true end + +local opt = options or {} +local isBatch = opt.batch +local cli = require 'cliargs' +local busted = require 'busted.core'() + +local configLoader = require 'busted.modules.configuration_loader'() +local outputHandlerLoader = require 'busted.modules.output_handler_loader'() + +local luacov = require 'busted.modules.luacov'() + +require 'busted.init'(busted) + +-- Default cli arg values +local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' +local defaultLoaders = 'lua,moonscript' +local defaultPattern = '_spec' +local defaultSeed = 'os.time()' +local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' +local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' + +local fileName = debug.getinfo(2).short_src + +-- Load up the command-line interface options +cli:set_name(path.basename(fileName)) +cli:add_flag('--version', 'prints the program version and exits') + +if isBatch then + cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1) + + cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern) +end + +cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput) +cli:add_option('-d, --cwd=cwd', 'path to current working directory', './') +cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags') +cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags') +cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) +cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) +cli:add_option('-r, --run=RUN', 'config to run from .busted file') +cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1') +cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed) +cli:add_option('--lang=LANG', 'language for error messages', 'en') +cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) +cli:add_option('--helper=PATH', 'A helper script that is run before tests') + +cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') +cli:add_flag('-v, --verbose', 'verbose output of errors') +cli:add_flag('-s, --enable-sound', 'executes `say` command if available') +cli:add_flag('--randomize', 'force randomized test order') +cli:add_flag('--shuffle', 'force randomized test order (alias for randomize)') +cli:add_flag('--suppress-pending', 'suppress `pending` test output') +cli:add_flag('--defer-print', 'defer print to when test suite is complete') + +-- Parse the cli arguments +local cliArgs, hasError = cli:parse() +if hasError then + os.exit(1) +end + +-- Return early if only asked for the version +if cliArgs.version then + print(busted.version) + os.exit(0) +end + +-- Load current working directory +local fpath = cliArgs.d + +-- Load busted config file if available +local configFile = { } +local bustedConfigFilePath = normpath(path.join(fpath, '.busted')) + +local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) + +if bustedConfigFile then + local config, err = configLoader(configFile, cliArgs) + + if err then + print(err) + else + cliArgs = config + end +end + +local tags = {} +local excludeTags = {} + +if cliArgs.t ~= '' then + tags = utils.split(cliArgs.t, ',') +end + +if cliArgs['exclude-tags'] ~= '' then + excludeTags = utils.split(cliArgs['exclude-tags'], ',') +end + +-- If coverage arg is passed in, load LuaCovsupport +if cliArgs.coverage then + luacov() +end + +-- Add additional package paths based on lpath and cpath cliArgs +if #cliArgs.lpath > 0 then + lpathprefix = cliArgs.lpath + lpathprefix = lpathprefix:gsub('^%.[/%\\]', fpath ) + lpathprefix = lpathprefix:gsub(';%.[/%\\]', ';' .. fpath) + package.path = (lpathprefix .. ';' .. package.path):gsub(';;',';') +end + +if #cliArgs.cpath > 0 then + cpathprefix = cliArgs.cpath + cpathprefix = cpathprefix:gsub('^%.[/%\\]', fpath ) + cpathprefix = cpathprefix:gsub(';%.[/%\\]', ';' .. fpath) + package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') +end + +if cliArgs.helper ~= '' then + dofile(cliArgs.helper) +end + +local loaders = {} +if #cliArgs.loaders > 0 then + string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) +end + +-- We report an error if the same tag appears in both `options.tags` +-- and `options.excluded_tags` because it does not make sense for the +-- user to tell Busted to include and exclude the same tests at the +-- same time. +for _, excluded in pairs(excludeTags) do + for _, included in pairs(tags) do + if excluded == included then + print('Cannot use --tags and --exclude-tags for the same tags') + os.exit(1) + end + end +end + +-- watch for test errors +local failures = 0 +local errors = 0 + +busted.subscribe({ 'error' }, function(element, parent, status) + if element.descriptor == 'output' then + print('Cannot load output library: ' .. element.name) + end + errors = errors + 1 + return nil, true +end) + +busted.subscribe({ 'failure' }, function(element, parent, status) + if element.descriptor == 'it' then + failures = failures + 1 + else + errors = errors + 1 + end + return nil, true +end) + +-- Set up randomization options +busted.randomize = cliArgs.randomize or cliArgs.shuffle +busted.randomseed = tonumber(cliArgs.seed) or os.time() +if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then + print('Argument to --seed must be a number') + errors = errors + 1 +end + +-- Set up output handler to listen to events +local outputHandlerOptions = { + verbose = cliArgs.verbose, + suppressPending = cliArgs['suppress-pending'], + language = cliArgs.lang, + deferPrint = cliArgs['defer-print'] +} + +local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted, defaultOutput) +outputHandler:subscribe(outputHandlerOptions) + +if cliArgs.s then + require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) +end + +local hasTag = function(name, tag) + local found = name:find('#' .. tag) + return (found ~= nil) +end + +local checkTags = function(name) + for i, tag in pairs(excludeTags) do + if hasTag(name, tag) then + return nil, false + end + end + + for i, tag in pairs(tags) do + if hasTag(name, tag) then + return nil, true + end + end + + return nil, (#tags == 0) +end + +if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then + -- Watch for tags + busted.subscribe({ 'register', 'it' }, checkTags, { priority = 1 }) + busted.subscribe({ 'register', 'pending' }, checkTags, { priority = 1 }) +end + +-- Load test directory +local rootFile = cliArgs.ROOT and normpath(path.join(fpath, cliArgs.ROOT)) or fileName +local pattern = cliArgs.pattern +local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) +local fileList = testFileLoader(rootFile, pattern) +if #fileList == 0 then + print('No test files found matching Lua pattern: ' .. pattern) + errors = errors + 1 +end + +busted.subscribe({'suite', 'repeat'}, function() + local oldctx = busted.context.get() + local children = busted.context.children(oldctx) + + busted.context.clear() + local ctx = busted.context.get() + for k, v in pairs(oldctx) do + ctx[k] = v + end + + for _, child in pairs(children) do + for descriptor, _ in pairs(busted.executors) do + child[descriptor] = nil + end + busted.context.attach(child) + end + + busted.randomseed = tonumber(cliArgs.seed) or os.time() + + return nil, true +end) + +local runs = tonumber(cliArgs['repeat']) or 1 +local runString = (runs > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') +for i = 1, runs do + io.write(runString:format(i, runs)) + io.flush() + if i > 1 then + busted.publish({ 'suite', 'repeat' }) + end + + busted.publish({ 'suite', 'start' }) + busted.execute() + busted.publish({ 'suite', 'end' }) +end + +local exit = 0 +if failures > 0 or errors > 0 then + exit = failures + errors + if exit > 255 then + exit = 255 + end +end +os.exit(exit) + +end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 8b08a8b3..2ee536d2 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -185,6 +185,78 @@ describe('Tests failing tests through the commandline', function() end) end) +describe('Test busted running standalone', function() + it('tests running with --tags specified', function() + local success, exitcode + error_start() + success, exitcode = execute('lua spec/cl_standalone.lua') + assert.is_false(success) + assert.is_equal(3, exitcode) + success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag1') + assert.is_false(success) + assert.is_equal(2, exitcode) + success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag1,tag2') + assert.is_false(success) + assert.is_equal(3, exitcode) + error_end() + end) + + it('tests running with --exclude-tags specified', function() + local success, exitcode + error_start() + success, exitcode = execute('lua spec/cl_standalone.lua --exclude-tags=tag1,tag2') + assert.is_true(success) + assert.is_equal(0, exitcode) + success, exitcode = execute('lua spec/cl_standalone.lua --exclude-tags=tag2') + assert.is_false(success) + assert.is_equal(2, exitcode) + error_end() + end) + + it('tests running with --tags and --exclude-tags specified', function () + local success, exitcode + error_start() + success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag1 --exclude-tags=tag1') + assert.is_false(success) + assert.is_equal(1, exitcode) + success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag3 --exclude-tags=tag4') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) + + it('tests running with --version specified', function() + local success, exitcode + success, exitcode = execute('lua spec/cl_standalone.lua --version') + assert.is_true(success) + assert.is_equal(0, exitcode) + end) + + it('tests running with --help specified', function() + local success, exitcode + success, exitcode = execute('lua spec/cl_standalone.lua --help') + assert.is_false(success) + assert.is_equal(1, exitcode) + end) +end) + +describe('Test busted command-line runner', function() + it('runs standalone spec', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted spec/cl_standalone.lua') + assert.is_false(success) + assert.is_equal(3, exitcode) + success, exitcode = execute('bin/busted --tags=tag1 spec/cl_standalone.lua') + assert.is_false(success) + assert.is_equal(2, exitcode) + success, exitcode = execute('bin/busted --tags=tag1,tag2 spec/cl_standalone.lua') + assert.is_false(success) + assert.is_equal(3, exitcode) + error_end() + end) +end) + describe('Tests distinguish between errors and failures', function() it('by detecting errors as test errors', function() error_start() diff --git a/spec/cl_standalone.lua b/spec/cl_standalone.lua new file mode 100644 index 00000000..883d605e --- /dev/null +++ b/spec/cl_standalone.lua @@ -0,0 +1,29 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +require 'busted.runner'() + +describe('Tests busted standalone with command-line options', function() + + it('is a test with a tag #tag1', function() + -- works by counting failure + error('error 1 on tag1') + end) + + it('is a test with a tag #tag1', function() + -- works by counting failure + error('error 2 on tag1') + end) + + it('is a test with a tag #tag2', function() + -- works by counting failure + error('error on tag2') + end) + + it('is a test with a tag #tag3', function() + -- nothing here, makes it succeed + end) + + it('is a test with two tags #tag3 #tag4', function () + -- Always succeed + end) +end) From d89603c4dda95ec8a310ad16e3a1edb6a6352bf7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 17 Dec 2014 21:19:09 -0800 Subject: [PATCH 066/293] Fix indent in runner --- busted/runner.lua | 424 +++++++++++++++++++++++----------------------- 1 file changed, 211 insertions(+), 213 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 080c4468..fd012cd0 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -38,270 +38,268 @@ local function normpath(fpath) end return function(options) + if loaded then return else loaded = true end -if loaded then return else loaded = true end + local opt = options or {} + local isBatch = opt.batch + local cli = require 'cliargs' + local busted = require 'busted.core'() -local opt = options or {} -local isBatch = opt.batch -local cli = require 'cliargs' -local busted = require 'busted.core'() + local configLoader = require 'busted.modules.configuration_loader'() + local outputHandlerLoader = require 'busted.modules.output_handler_loader'() -local configLoader = require 'busted.modules.configuration_loader'() -local outputHandlerLoader = require 'busted.modules.output_handler_loader'() + local luacov = require 'busted.modules.luacov'() -local luacov = require 'busted.modules.luacov'() + require 'busted.init'(busted) -require 'busted.init'(busted) + -- Default cli arg values + local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' + local defaultLoaders = 'lua,moonscript' + local defaultPattern = '_spec' + local defaultSeed = 'os.time()' + local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' + local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' --- Default cli arg values -local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' -local defaultLoaders = 'lua,moonscript' -local defaultPattern = '_spec' -local defaultSeed = 'os.time()' -local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' -local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' + local fileName = debug.getinfo(2).short_src -local fileName = debug.getinfo(2).short_src + -- Load up the command-line interface options + cli:set_name(path.basename(fileName)) + cli:add_flag('--version', 'prints the program version and exits') --- Load up the command-line interface options -cli:set_name(path.basename(fileName)) -cli:add_flag('--version', 'prints the program version and exits') + if isBatch then + cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1) -if isBatch then - cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1) - - cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern) -end + cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern) + end -cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput) -cli:add_option('-d, --cwd=cwd', 'path to current working directory', './') -cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags') -cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags') -cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) -cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) -cli:add_option('-r, --run=RUN', 'config to run from .busted file') -cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1') -cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed) -cli:add_option('--lang=LANG', 'language for error messages', 'en') -cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) -cli:add_option('--helper=PATH', 'A helper script that is run before tests') - -cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') -cli:add_flag('-v, --verbose', 'verbose output of errors') -cli:add_flag('-s, --enable-sound', 'executes `say` command if available') -cli:add_flag('--randomize', 'force randomized test order') -cli:add_flag('--shuffle', 'force randomized test order (alias for randomize)') -cli:add_flag('--suppress-pending', 'suppress `pending` test output') -cli:add_flag('--defer-print', 'defer print to when test suite is complete') - --- Parse the cli arguments -local cliArgs, hasError = cli:parse() -if hasError then - os.exit(1) -end + cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput) + cli:add_option('-d, --cwd=cwd', 'path to current working directory', './') + cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags') + cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags') + cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) + cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) + cli:add_option('-r, --run=RUN', 'config to run from .busted file') + cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1') + cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed) + cli:add_option('--lang=LANG', 'language for error messages', 'en') + cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) + cli:add_option('--helper=PATH', 'A helper script that is run before tests') + + cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') + cli:add_flag('-v, --verbose', 'verbose output of errors') + cli:add_flag('-s, --enable-sound', 'executes `say` command if available') + cli:add_flag('--randomize', 'force randomized test order') + cli:add_flag('--shuffle', 'force randomized test order (alias for randomize)') + cli:add_flag('--suppress-pending', 'suppress `pending` test output') + cli:add_flag('--defer-print', 'defer print to when test suite is complete') + + -- Parse the cli arguments + local cliArgs, hasError = cli:parse() + if hasError then + os.exit(1) + end --- Return early if only asked for the version -if cliArgs.version then - print(busted.version) - os.exit(0) -end + -- Return early if only asked for the version + if cliArgs.version then + print(busted.version) + os.exit(0) + end --- Load current working directory -local fpath = cliArgs.d + -- Load current working directory + local fpath = cliArgs.d --- Load busted config file if available -local configFile = { } -local bustedConfigFilePath = normpath(path.join(fpath, '.busted')) + -- Load busted config file if available + local configFile = { } + local bustedConfigFilePath = normpath(path.join(fpath, '.busted')) -local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) + local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) -if bustedConfigFile then - local config, err = configLoader(configFile, cliArgs) + if bustedConfigFile then + local config, err = configLoader(configFile, cliArgs) - if err then - print(err) - else - cliArgs = config + if err then + print(err) + else + cliArgs = config + end end -end -local tags = {} -local excludeTags = {} + local tags = {} + local excludeTags = {} -if cliArgs.t ~= '' then - tags = utils.split(cliArgs.t, ',') -end + if cliArgs.t ~= '' then + tags = utils.split(cliArgs.t, ',') + end -if cliArgs['exclude-tags'] ~= '' then - excludeTags = utils.split(cliArgs['exclude-tags'], ',') -end + if cliArgs['exclude-tags'] ~= '' then + excludeTags = utils.split(cliArgs['exclude-tags'], ',') + end --- If coverage arg is passed in, load LuaCovsupport -if cliArgs.coverage then - luacov() -end + -- If coverage arg is passed in, load LuaCovsupport + if cliArgs.coverage then + luacov() + end --- Add additional package paths based on lpath and cpath cliArgs -if #cliArgs.lpath > 0 then - lpathprefix = cliArgs.lpath - lpathprefix = lpathprefix:gsub('^%.[/%\\]', fpath ) - lpathprefix = lpathprefix:gsub(';%.[/%\\]', ';' .. fpath) - package.path = (lpathprefix .. ';' .. package.path):gsub(';;',';') -end + -- Add additional package paths based on lpath and cpath cliArgs + if #cliArgs.lpath > 0 then + lpathprefix = cliArgs.lpath + lpathprefix = lpathprefix:gsub('^%.[/%\\]', fpath ) + lpathprefix = lpathprefix:gsub(';%.[/%\\]', ';' .. fpath) + package.path = (lpathprefix .. ';' .. package.path):gsub(';;',';') + end -if #cliArgs.cpath > 0 then - cpathprefix = cliArgs.cpath - cpathprefix = cpathprefix:gsub('^%.[/%\\]', fpath ) - cpathprefix = cpathprefix:gsub(';%.[/%\\]', ';' .. fpath) - package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') -end + if #cliArgs.cpath > 0 then + cpathprefix = cliArgs.cpath + cpathprefix = cpathprefix:gsub('^%.[/%\\]', fpath ) + cpathprefix = cpathprefix:gsub(';%.[/%\\]', ';' .. fpath) + package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') + end -if cliArgs.helper ~= '' then - dofile(cliArgs.helper) -end + if cliArgs.helper ~= '' then + dofile(cliArgs.helper) + end -local loaders = {} -if #cliArgs.loaders > 0 then - string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) -end + local loaders = {} + if #cliArgs.loaders > 0 then + string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) + end --- We report an error if the same tag appears in both `options.tags` --- and `options.excluded_tags` because it does not make sense for the --- user to tell Busted to include and exclude the same tests at the --- same time. -for _, excluded in pairs(excludeTags) do - for _, included in pairs(tags) do - if excluded == included then - print('Cannot use --tags and --exclude-tags for the same tags') - os.exit(1) + -- We report an error if the same tag appears in both `options.tags` + -- and `options.excluded_tags` because it does not make sense for the + -- user to tell Busted to include and exclude the same tests at the + -- same time. + for _, excluded in pairs(excludeTags) do + for _, included in pairs(tags) do + if excluded == included then + print('Cannot use --tags and --exclude-tags for the same tags') + os.exit(1) + end end end -end --- watch for test errors -local failures = 0 -local errors = 0 + -- watch for test errors + local failures = 0 + local errors = 0 -busted.subscribe({ 'error' }, function(element, parent, status) - if element.descriptor == 'output' then - print('Cannot load output library: ' .. element.name) - end - errors = errors + 1 - return nil, true -end) - -busted.subscribe({ 'failure' }, function(element, parent, status) - if element.descriptor == 'it' then - failures = failures + 1 - else + busted.subscribe({ 'error' }, function(element, parent, status) + if element.descriptor == 'output' then + print('Cannot load output library: ' .. element.name) + end errors = errors + 1 - end - return nil, true -end) - --- Set up randomization options -busted.randomize = cliArgs.randomize or cliArgs.shuffle -busted.randomseed = tonumber(cliArgs.seed) or os.time() -if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then - print('Argument to --seed must be a number') - errors = errors + 1 -end - --- Set up output handler to listen to events -local outputHandlerOptions = { - verbose = cliArgs.verbose, - suppressPending = cliArgs['suppress-pending'], - language = cliArgs.lang, - deferPrint = cliArgs['defer-print'] -} + return nil, true + end) + + busted.subscribe({ 'failure' }, function(element, parent, status) + if element.descriptor == 'it' then + failures = failures + 1 + else + errors = errors + 1 + end + return nil, true + end) -local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted, defaultOutput) -outputHandler:subscribe(outputHandlerOptions) + -- Set up randomization options + busted.randomize = cliArgs.randomize or cliArgs.shuffle + busted.randomseed = tonumber(cliArgs.seed) or os.time() + if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then + print('Argument to --seed must be a number') + errors = errors + 1 + end -if cliArgs.s then - require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) -end + -- Set up output handler to listen to events + local outputHandlerOptions = { + verbose = cliArgs.verbose, + suppressPending = cliArgs['suppress-pending'], + language = cliArgs.lang, + deferPrint = cliArgs['defer-print'] + } -local hasTag = function(name, tag) - local found = name:find('#' .. tag) - return (found ~= nil) -end + local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted, defaultOutput) + outputHandler:subscribe(outputHandlerOptions) -local checkTags = function(name) - for i, tag in pairs(excludeTags) do - if hasTag(name, tag) then - return nil, false - end + if cliArgs.s then + require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) end - for i, tag in pairs(tags) do - if hasTag(name, tag) then - return nil, true - end + local hasTag = function(name, tag) + local found = name:find('#' .. tag) + return (found ~= nil) end - return nil, (#tags == 0) -end + local checkTags = function(name) + for i, tag in pairs(excludeTags) do + if hasTag(name, tag) then + return nil, false + end + end -if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then - -- Watch for tags - busted.subscribe({ 'register', 'it' }, checkTags, { priority = 1 }) - busted.subscribe({ 'register', 'pending' }, checkTags, { priority = 1 }) -end + for i, tag in pairs(tags) do + if hasTag(name, tag) then + return nil, true + end + end --- Load test directory -local rootFile = cliArgs.ROOT and normpath(path.join(fpath, cliArgs.ROOT)) or fileName -local pattern = cliArgs.pattern -local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) -local fileList = testFileLoader(rootFile, pattern) -if #fileList == 0 then - print('No test files found matching Lua pattern: ' .. pattern) - errors = errors + 1 -end + return nil, (#tags == 0) + end -busted.subscribe({'suite', 'repeat'}, function() - local oldctx = busted.context.get() - local children = busted.context.children(oldctx) + if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then + -- Watch for tags + busted.subscribe({ 'register', 'it' }, checkTags, { priority = 1 }) + busted.subscribe({ 'register', 'pending' }, checkTags, { priority = 1 }) + end - busted.context.clear() - local ctx = busted.context.get() - for k, v in pairs(oldctx) do - ctx[k] = v + -- Load test directory + local rootFile = cliArgs.ROOT and normpath(path.join(fpath, cliArgs.ROOT)) or fileName + local pattern = cliArgs.pattern + local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) + local fileList = testFileLoader(rootFile, pattern) + if #fileList == 0 then + print('No test files found matching Lua pattern: ' .. pattern) + errors = errors + 1 end - for _, child in pairs(children) do - for descriptor, _ in pairs(busted.executors) do - child[descriptor] = nil + busted.subscribe({'suite', 'repeat'}, function() + local oldctx = busted.context.get() + local children = busted.context.children(oldctx) + + busted.context.clear() + local ctx = busted.context.get() + for k, v in pairs(oldctx) do + ctx[k] = v end - busted.context.attach(child) - end - busted.randomseed = tonumber(cliArgs.seed) or os.time() + for _, child in pairs(children) do + for descriptor, _ in pairs(busted.executors) do + child[descriptor] = nil + end + busted.context.attach(child) + end - return nil, true -end) + busted.randomseed = tonumber(cliArgs.seed) or os.time() -local runs = tonumber(cliArgs['repeat']) or 1 -local runString = (runs > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') -for i = 1, runs do - io.write(runString:format(i, runs)) - io.flush() - if i > 1 then - busted.publish({ 'suite', 'repeat' }) - end + return nil, true + end) - busted.publish({ 'suite', 'start' }) - busted.execute() - busted.publish({ 'suite', 'end' }) -end + local runs = tonumber(cliArgs['repeat']) or 1 + local runString = (runs > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') + for i = 1, runs do + io.write(runString:format(i, runs)) + io.flush() + if i > 1 then + busted.publish({ 'suite', 'repeat' }) + end -local exit = 0 -if failures > 0 or errors > 0 then - exit = failures + errors - if exit > 255 then - exit = 255 + busted.publish({ 'suite', 'start' }) + busted.execute() + busted.publish({ 'suite', 'end' }) end -end -os.exit(exit) + local exit = 0 + if failures > 0 or errors > 0 then + exit = failures + errors + if exit > 255 then + exit = 255 + end + end + os.exit(exit) end From 6397decd75195e4a1086164a7417f136e719486c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 21 Dec 2014 01:10:07 -0800 Subject: [PATCH 067/293] Refactor runner to be compatible with live coding Support live coding with ZeroBrane Studio by replacing the function returned by loadfile(), which was read from the file system, with the calling function, which is currently loaded in memory. --- busted/runner.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/busted/runner.lua b/busted/runner.lua index fd012cd0..fd53d64b 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -1,5 +1,7 @@ -- Busted command-line runner +local getfenv = require 'busted.compatibility'.getfenv +local setfenv = require 'busted.compatibility'.setfenv local path = require 'pl.path' local utils = require 'pl.utils' local loaded = false @@ -60,7 +62,10 @@ return function(options) local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local fileName = debug.getinfo(2).short_src + local level = 2 + local info = debug.getinfo(level, 'Sf') + local source = info.source + local fileName = source:sub(1,1) == '@' and source:sub(2) or source -- Load up the command-line interface options cli:set_name(path.basename(fileName)) @@ -258,6 +263,12 @@ return function(options) errors = errors + 1 end + if not cliArgs.ROOT then + local ctx = busted.context.get() + local file = busted.context.children(ctx)[1] + getmetatable(file.run).__call = info.func + end + busted.subscribe({'suite', 'repeat'}, function() local oldctx = busted.context.get() local children = busted.context.children(oldctx) From b5a8993dce92be11bec78729e7632e7a85aa4dfd Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Wed, 31 Dec 2014 07:39:12 -0800 Subject: [PATCH 068/293] v2.0.rc5 --- busted-2.0.rc4-0.rockspec => busted-2.0.rc5-0.rockspec | 8 ++++---- busted/core.lua | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename busted-2.0.rc4-0.rockspec => busted-2.0.rc5-0.rockspec (96%) diff --git a/busted-2.0.rc4-0.rockspec b/busted-2.0.rc5-0.rockspec similarity index 96% rename from busted-2.0.rc4-0.rockspec rename to busted-2.0.rc5-0.rockspec index c56484c9..bf8da55d 100644 --- a/busted-2.0.rc4-0.rockspec +++ b/busted-2.0.rc5-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc4-0' +version = '2.0.rc5-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc4.tar.gz', - dir = 'busted-2.0.rc4' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc5.tar.gz', + dir = 'busted-2.0.rc5' } description = { summary = 'Elegant Lua unit testing.', @@ -23,7 +23,7 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.2-1', - 'luassert >= 1.7.2-0', + 'luassert >= 1.7.3-0', 'ansicolors >= 1.0-1', 'penlight >= 1.0.0-1', 'mediator_lua >= 1.1-3', diff --git a/busted/core.lua b/busted/core.lua index 39b967b1..00c6b1ee 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -31,7 +31,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc3-0' + busted.version = '2.0.rc5-0' local root = require 'busted.context'() busted.context = root.ref() From 1a37d4990e5fe1bd37e5c7f4288ce118d4cf2ad0 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 28 Dec 2014 23:46:04 -0800 Subject: [PATCH 069/293] Issue #241 Add bash autocompletion functions Add autocompletion for command-line options and their arguments. --- completions/bash/busted.bash | 104 +++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 completions/bash/busted.bash diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash new file mode 100644 index 00000000..b20171ea --- /dev/null +++ b/completions/bash/busted.bash @@ -0,0 +1,104 @@ +# bash completion for busted +# + +_busted() { + COMPREPLY=() + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + + case "${prev}" in + --lang) + local langs="ar de en fr ja nl ru th ua zh" + COMPREPLY=( $(compgen -W "${langs}" -- ${cur}) ) + return 0 + ;; + -o|--output) + local outputs="plainTerminal utfTerminal TAP json junit sound" + local -a toks + toks=( ${toks[@]-} $(compgen -W "${outputs}" -- ${cur} ) ) + toks=( ${toks[@]-} $(compgen -f -X "!*.lua" -- ${cur} ) ) + toks=( ${toks[@]-} $(compgen -f -X "!*.moon" -- ${cur} ) ) + toks=( ${toks[@]-} $(compgen -d -- ${cur} ) ) + _compopt_o_filenames + + COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" ) + return 0 + ;; + -r|--run) + local d="." + local i + for (( i=1; i < ${#COMP_WORDS[@]}-1; i++ )); do + case "${COMP_WORDS[i]}" in + -d|--cwd) + d="${COMP_WORDS[i+1]}" + ;; + esac + done + local cfgs=$(lua -e "cfgs=dofile('${d}/.busted')" \ + -e "for k,_ in pairs(cfgs) do print(k) end" 2> /dev/null) + COMPREPLY=( $(compgen -W "${cfgs}" -- ${cur}) ) + return 0 + ;; + --loaders) + local prefix=${cur%,*} + local cur_=${cur##*,} + local loaders="lua moonscript terra" + local -a toks + toks=( ${toks[@]-} $(compgen -W "${loaders[@]}" -- ${cur} ) ) + if [[ "${prefix}" != "${cur}" ]]; then + local mloaders="" + for l in ${loaders}; do + if ! [[ "${prefix}," =~ .*,$l,.* || "${prefix}," =~ ^$l,.* ]]; then + mloaders="${mloaders} $l" + fi + done + toks=( ${toks[@]-} $(compgen -P "${prefix}," -W "${mloaders}" -- ${cur_} ) ) + fi + compopt -o nospace + + COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" ) + return 0 + ;; + -d|--cwd) + _filedir -d + return 0 + ;; + --helper) + _filedir + return 0 + ;; + -p|--pattern) + # no completion available + return 0 + ;; + -t|--tags|--exclude-tags) + # no completion available + return 0 + ;; + -m|--lpath|--cpath) + _filedir + return 0 + ;; + --repeat) + # no completion available + return 0 + ;; + --seed) + # no completion available + return 0 + ;; + esac + + if [[ ${cur} == -* ]] ; then + local opts="-h --help -v --verbose --version -o --output -p --pattern \ + -d --cwd -t --tags --exclude-tags -m --lpath --cpath -r --run --repeat \ + --seed --lang --loaders --helper -c --coverage -s --enable-sound \ + --randomize --shuffle --supress-pending --defer-print" + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + else + _filedir + fi +} + +complete -F _busted busted From fa85cf3c6b4333c61b41fa40b043ab493f56d469 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 30 Dec 2014 00:41:33 -0800 Subject: [PATCH 070/293] Issue #241 Bash autocompletion with '=' options Update bash autocompletion to automatically append '=' to long options that take arguments. --- completions/bash/busted.bash | 51 +++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index b20171ea..fea4f21b 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -1,11 +1,29 @@ # bash completion for busted # +_busted_comp() { + local opt IFS=' '$'\t'$'\n' + for opt in $1; do + case $opt in + --*=*) printf %s$'\n' "$opt" ;; + *.) printf %s$'\n' "$opt" ;; + *) printf %s$'\n' "$opt " ;; + esac + done +} + _busted() { COMPREPLY=() local cur="${COMP_WORDS[COMP_CWORD]}" local prev="${COMP_WORDS[COMP_CWORD-1]}" + if [[ "${cur}" == "=" ]]; then + cur= + fi + if [[ "${prev}" == "=" ]]; then + prev="${COMP_WORDS[COMP_CWORD-2]}" + fi + case "${prev}" in --lang) local langs="ar de en fr ja nl ru th ua zh" @@ -76,7 +94,7 @@ _busted() { return 0 ;; -m|--lpath|--cpath) - _filedir + _filedir -d return 0 ;; --repeat) @@ -89,12 +107,31 @@ _busted() { ;; esac - if [[ ${cur} == -* ]] ; then - local opts="-h --help -v --verbose --version -o --output -p --pattern \ - -d --cwd -t --tags --exclude-tags -m --lpath --cpath -r --run --repeat \ - --seed --lang --loaders --helper -c --coverage -s --enable-sound \ - --randomize --shuffle --supress-pending --defer-print" - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + if [[ "${cur}" == -* ]] ; then + local opts=" + -h --help + -v --verbose + --version + -o --output= + -p --pattern= + -d --cwd= + -t --tags= --exclude-tags= + -m --lpath= --cpath= + -r --run= + --repeat= + --seed= + --lang= + --loaders= + --helper= + -c --coverage + -s --enable-sound + --randomize --shuffle + --supress-pending + --defer-print" + compopt -o nospace + + local IFS=$'\n' + COMPREPLY=( $(compgen -W "$(_busted_comp "${opts-}")" -- "${cur}" )) return 0 else _filedir From e201cffcbeeba42e4faab12be425a9adc1469b59 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 30 Dec 2014 00:47:15 -0800 Subject: [PATCH 071/293] Issue #241 Update zsh autocompletion functions Add missing command-line options/flags, and remove unsupported options/flags. --- completions/zsh/_busted | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 7bf7ed08..3996549f 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -6,15 +6,19 @@ local -a _busted_args _busted_args=( "--cpath=:Optional path to be prefixed to the Lua C module search path (default: ./csrc/?.so;./csrc/?/?.so;)" -"--defer-print:Print to when test suite is complete" +"--defer-print:Defer print to when test suite is complete" "--exclude-tags=:Do not run tests with these #tags, takes precedence over --tags" "--lang=:Language for error messages (default: en)" -"--suppress-pending:'pending' test output" +"--repeat=:Run the tests repeatedly (default: 1)" +"--seed=:Random seed value to use for shuffing test order (default: os.time())" +"--randomize:Force randomized test order" +"--shuffle:Force randomized test order (alias for --randomize)" +"--suppress-pending:Supress 'pending' test output" "--version:Prints the program's version and exits" +"--helper:A helper script that is run before tests" "-c:Do code coverage analysis (requires 'LuaCov' to be installed) --coverage " "-d:Path to current working directory (default: ./) --cwd=cwd " "-h:Help" -"-l:Path to the execution environment (luajit or lua), picks first available (default: luajit) --lua=luajit " "-m:Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua) --lpath=path " "-o:Output library to load (default: utf_terminal) --output=LIBRARY " "-p:Only run test files matching the Lua pattern (default: _spec) --pattern=pattern " From 06b5d9b3f1420e604e9f4a69aee82f3d7d50b653 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 31 Dec 2014 14:27:55 -0800 Subject: [PATCH 072/293] Issue #241 Zsh autocompletion for arguments Add missing long options to autocompletion, and autocomplete arguments to command-line options. --- completions/zsh/_busted | 73 ++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 3996549f..72e56333 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -3,29 +3,56 @@ #alias rbu="unfunction _busted; autoload -U _busted" -local -a _busted_args +local _busted_args _busted_args=( -"--cpath=:Optional path to be prefixed to the Lua C module search path (default: ./csrc/?.so;./csrc/?/?.so;)" -"--defer-print:Defer print to when test suite is complete" -"--exclude-tags=:Do not run tests with these #tags, takes precedence over --tags" -"--lang=:Language for error messages (default: en)" -"--repeat=:Run the tests repeatedly (default: 1)" -"--seed=:Random seed value to use for shuffing test order (default: os.time())" -"--randomize:Force randomized test order" -"--shuffle:Force randomized test order (alias for --randomize)" -"--suppress-pending:Supress 'pending' test output" -"--version:Prints the program's version and exits" -"--helper:A helper script that is run before tests" -"-c:Do code coverage analysis (requires 'LuaCov' to be installed) --coverage " -"-d:Path to current working directory (default: ./) --cwd=cwd " -"-h:Help" -"-m:Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua) --lpath=path " -"-o:Output library to load (default: utf_terminal) --output=LIBRARY " -"-p:Only run test files matching the Lua pattern (default: _spec) --pattern=pattern " -"-r:Config to run from .busted file --run=run " -"-s:Executes 'say' command if available --enable-sound " -"-t:Only run tests with these #tags --tags=tags " -"-v:Verbose output of errors --verbose " +"--cpath=[Optional path to be prefixed to the Lua C module search path (default: ./csrc/?.so;./csrc/?/?.so;)]:directory:_dirs" +"--defer-print[Defer print to when test suite is complete]" +"--lang=[Language for error messages (default: en)]:languages:(ar de en fr ja nl ru th ua zh)" +"--repeat=[Run the tests repeatedly (default: 1)]: :" +"--seed=[Random seed value to use for shuffing test order (default: os.time())]: :" +"(--randomize --shuffle)--randomize[Force randomized test order]" +"(--randomize --shuffle)--shuffle[Force randomized test order (alias for --randomize)]" +"--suppress-pending[Suppress 'pending' test output]" +"--version[Prints the program version and exits]" +"--helper[A helper script that is run before tests]:files:_files" +"--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" +"(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" +"(-d --cwd)"{-d,--cwd=}"[Path to current working directory (default: ./)]:directory:_dirs" +"(-h --help)"{-h,--help}"[Help]" +"(-m --lpath)"{-m,--lpath=}"[Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua)]:directory:_dirs" +"(-o --output)"{-o,--output=}"[Output library to load (default: utfTerminal)]:output handlers:->output" +"(-p --pattern)"{-p,--pattern=}"[Only run test files matching the Lua pattern (default: _spec)]: :" +"(-r --run)"{-r,--run=}"[Config to run from .busted file]:run configurations:->run" +"(-s --enable-sound)"{-s,--enable-sound}"[Executes 'say' command if available]" +"(-t --tags --exclude-tags)"{-t,--tags=}"[Only run tests with these #tags]: :" +"(-t --tags --exclude-tags)--exclude-tags=[Do not run tests with these #tags, takes precedence over --tags]: :" +"(-v --verbose)"{-v,--verbose}"[Verbose output of errors]" +"*:files:_files" ) -_describe -t commands "busted args" _busted_args +local curcontext="${curcontext}" state line +typeset -A opt_args + +_arguments -s $_busted_args + +case "${state}" in + run) + local d="." + local i + for (( i=1; i < ${#words}-1; i++ )); do + case "${words[i]}" in + -d|--cwd) + d="${words[i+1]}" + ;; + esac + done + local cfgs + cfgs=$(lua -e "cfgs=dofile('${d}/.busted')" \ + -e "for k,_ in pairs(cfgs) do print(k) end" 2> /dev/null) + _arguments -s "*:run configurations:(${cfgs})" + ;; + output) + _alternative "*:output handlers:(plainTerminal utfTerminal TAP json junit sound)" + _arguments -s "*:output handlers:_files -g '*.lua *.moon'" + ;; +esac From 87e10821eeb9001758066e55c486e068479b01fe Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 31 Dec 2014 01:41:10 -0800 Subject: [PATCH 073/293] Fix error message when pcall occurs before assert This fixes the case where the file, line number, and error message reported are incorrect, showing the error message for a previous call to `error()` that was caught with a `pcall()`. describe('Test assert after pcall', function() it('should report line number of assert', function() local ok, msg = pcall(function() error('error message') end) assert(false, 'should report this line number') end) end) In the above example, the error message reported would be from the `pcall()`, instead of the error message from the `assert()`, where the actual test failure occurred. The solution is to not replace `error` in the test environment. This can lead to more inconsistent error messages that may be difficult to trace. Go back to rewriting the error message to insert the file and line information for complex error objects. --- busted/core.lua | 69 +++++++++++++---------------- busted/modules/files/moonscript.lua | 2 +- spec/cl_error_messages.lua | 9 ++++ spec/cl_spec.lua | 26 +++++++++-- 4 files changed, 64 insertions(+), 42 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 00c6b1ee..d11da0b2 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -1,17 +1,17 @@ -local function metatype(obj) - local otype = type(obj) - if otype == 'table' then - local mt = getmetatable(obj) - if mt and mt.__type then - return mt.__type - end - end - return otype -end +local getfenv = require 'busted.compatibility'.getfenv +local setfenv = require 'busted.compatibility'.setfenv +local unpack = require 'busted.compatibility'.unpack +local pretty = require 'pl.pretty' +local throw = error local failureMt = { __index = {}, - __tostring = function(e) return e.message end, + __tostring = function(e) return tostring(e.message) end, + __type = 'failure' +} + +local failureMtNoString = { + __index = {}, __type = 'failure' } @@ -21,11 +21,14 @@ local pendingMt = { __type = 'pending' } -local getfenv = require 'busted.compatibility'.getfenv -local setfenv = require 'busted.compatibility'.setfenv -local unpack = require 'busted.compatibility'.unpack -local pretty = require 'pl.pretty' -local throw = error +local function metatype(obj) + local otype = type(obj) + return otype == 'table' and (getmetatable(obj) or {}).__type or otype +end + +local function hasToString(obj) + return type(obj) == 'string' or (getmetatable(obj) or {}).__tostring +end return function() local mediator = require 'mediator'() @@ -60,20 +63,20 @@ return function() return file.getTrace(file.name, info) end - function busted.getErrorMessage(err) - if getmetatable(err) and getmetatable(err).__tostring then - return tostring(err) - elseif type(err) ~= 'string' then - return err and pretty.write(err) or 'Nil error' - end - - return err - end - function busted.rewriteMessage(element, message, trace) local file = busted.getFile(element) + local msg = hasToString(message) and tostring(message) + msg = msg or (message ~= nil and pretty.write(message) or 'Nil error') + msg = (file.rewriteMessage and file.rewriteMessage(file.name, msg) or msg) + + local hasFileLine = msg:match('^[^\n]-:%d+: .*') + if not hasFileLine then + local trace = trace or busted.getTrace(element, 3, message) + local fileline = trace.short_src .. ':' .. trace.currentline .. ': ' + msg = fileline .. msg + end - return file.rewriteMessage and file.rewriteMessage(file.name, message) or message + return msg end function busted.publish(...) @@ -114,7 +117,7 @@ return function() function busted.fail(msg, level) local _, emsg = pcall(throw, msg, level+2) local e = { message = emsg } - setmetatable(e, failureMt) + setmetatable(e, hasToString(msg) and failureMt or failureMtNoString) throw(e, level+1) end @@ -144,19 +147,11 @@ return function() local trace, message local status = 'success' - if not element.env then element.env = {} end - - element.env.error = function(msg, level) - local level = level or 1 - _, message = pcall(throw, busted.getErrorMessage(msg), level+2) - error(msg, level+1) - end - local ret = { xpcall(run, function(msg) local errType = metatype(msg) status = ((errType == 'pending' or errType == 'failure') and errType or 'error') trace = busted.getTrace(element, 3, msg) - message = busted.rewriteMessage(element, message or tostring(msg), trace) + message = busted.rewriteMessage(element, msg, trace) end) } if not ret[1] then diff --git a/busted/modules/files/moonscript.lua b/busted/modules/files/moonscript.lua index acd0219d..ba428c3d 100644 --- a/busted/modules/files/moonscript.lua +++ b/busted/modules/files/moonscript.lua @@ -81,7 +81,7 @@ local getTrace = function(filename, info) end local rewriteMessage = function(filename, message) - local fname, line, msg = message:match('(.-):(%d+): (.*)') + local fname, line, msg = message:match('^([^\n]-):(%d+): (.*)') if not fname then return message end diff --git a/spec/cl_error_messages.lua b/spec/cl_error_messages.lua index 4eda92ed..a76bcfd0 100644 --- a/spec/cl_error_messages.lua +++ b/spec/cl_error_messages.lua @@ -12,4 +12,13 @@ describe('Test error messages show file and line for', function() it('string errors #string', function() error('error message') end) + + it('table errors #tostring', function() + error(setmetatable({}, { __tostring = function() return '{}' end})) + end) + + it('table errors #pcall', function() + pcall(error, 'error inside pcall') + error('error after pcall') + end) end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 2ee536d2..64da3266 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -331,7 +331,7 @@ describe('Tests error messages through the command line', function() error_end() end) - it('when throwning an error table', function() + it('when throwing an error table', function() error_start() local result = run('bin/busted --output=plainTerminal --tags=table --pattern=cl_error_messages.lua$') local errmsg = result:match('\n(%./spec/.-)\n') @@ -340,7 +340,7 @@ describe('Tests error messages through the command line', function() error_end() end) - it('when throwning a nil error', function() + it('when throwing a nil error', function() error_start() local result = run('bin/busted --output=plainTerminal --tags=nil --pattern=cl_error_messages.lua$') local errmsg = result:match('\n(%./spec/.-)\n') @@ -349,6 +349,24 @@ describe('Tests error messages through the command line', function() error_end() end) + it('when throwing an error table with __tostring', function() + error_start() + local result = run('bin/busted --output=plainTerminal --tags=tostring --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%./spec/.-)\n') + local expected = './spec/cl_error_messages.lua:17: {}' + assert.is_equal(expected, errmsg) + error_end() + end) + + it('when throwing after a pcall', function() + error_start() + local result = run('bin/busted --output=plainTerminal --tags=pcall --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%./spec/.-)\n') + local expected = './spec/cl_error_messages.lua:22: error after pcall' + assert.is_equal(expected, errmsg) + error_end() + end) + it('when running a non-compiling testfile', function() error_start() local result = run('bin/busted --output=plainTerminal --pattern=cl_compile_fail.lua$') @@ -414,7 +432,7 @@ describe('Tests moonscript error messages through the command line', function() error_end() end) - it('when throwning an error table', function() + it('when throwing an error table', function() error_start() local result = run('bin/busted --output=plainTerminal --tags=table --pattern=cl_moonscript_error_messages.moon$') local errmsg = result:match('\n(%./spec/.-)\n') @@ -423,7 +441,7 @@ describe('Tests moonscript error messages through the command line', function() error_end() end) - it('when throwning a nil error', function() + it('when throwing a nil error', function() error_start() local result = run('bin/busted --output=plainTerminal --tags=nil --pattern=cl_moonscript_error_messages.moon$') local errmsg = result:match('\n(%./spec/.-)\n') From edca20aea7148dc05bb15efc0d003271bf81fd09 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 1 Jan 2015 02:57:45 -0800 Subject: [PATCH 074/293] Fix error when function is used as callable object --- busted/core.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index d11da0b2..4f8260e2 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -129,7 +129,7 @@ return function() function busted.replaceErrorWithFail(callable) local env = {} - local f = getmetatable(callable).__call or callable + local f = (getmetatable(callable) or {}).__call or callable setmetatable(env, { __index = getfenv(f) }) env.error = busted.fail setfenv(f, env) @@ -138,7 +138,7 @@ return function() function busted.wrapEnv(callable) if (type(callable) == 'function' or getmetatable(callable).__call) then -- prioritize __call if it exists, like in files - environment.wrap(getmetatable(callable).__call or callable) + environment.wrap((getmetatable(callable) or {}).__call or callable) end end From c9e3a36811a70e8b9954eacc00ca43f983c74bd6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 1 Jan 2015 02:59:58 -0800 Subject: [PATCH 075/293] Fix error level reporting --- busted/core.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 4f8260e2..fe802546 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -115,10 +115,12 @@ return function() end function busted.fail(msg, level) - local _, emsg = pcall(throw, msg, level+2) + local rawlevel = (type(level) ~= 'number' or level <= 0) and level + local level = level or 1 + local _, emsg = pcall(throw, msg, rawlevel or level+2) local e = { message = emsg } setmetatable(e, hasToString(msg) and failureMt or failureMtNoString) - throw(e, level+1) + throw(e, rawlevel or level+1) end function busted.pending(msg) From d2abcc78ca5b929adc1394a6fa897fc13d8baea6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 2 Jan 2015 01:21:58 -0800 Subject: [PATCH 076/293] Fix getTrace() to search based on busted dirname --- busted/core.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/busted/core.lua b/busted/core.lua index fe802546..758c60ad 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -1,6 +1,7 @@ local getfenv = require 'busted.compatibility'.getfenv local setfenv = require 'busted.compatibility'.setfenv local unpack = require 'busted.compatibility'.unpack +local path = require 'pl.path' local pretty = require 'pl.pretty' local throw = error @@ -49,9 +50,10 @@ return function() function busted.getTrace(element, level, msg) level = level or 3 + local thisdir = path.dirname(debug.getinfo(1, 'Sl').source) local info = debug.getinfo(level, 'Sl') while info.what == 'C' or info.short_src:match('luassert[/\\].*%.lua$') or - info.short_src:match('busted[/\\].*%.lua$') do + (info.source:sub(1,1) == '@' and thisdir == path.dirname(info.source)) do level = level + 1 info = debug.getinfo(level, 'Sl') end From b647c3dcf5c9ca433db7df394eea8882b7164348 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 6 Jan 2015 01:19:27 -0800 Subject: [PATCH 077/293] Issue #320 Access spec declaration methods This allows helper modules to declare tests like the following: -- test_helper.lua local it = require 'busted'.it local function make_test(a, b) it('should check ' .. a .. ' same as ' .. b, function() assert.same(a, b) end) end return { make_test = make_test } And then use the helper modules like this: -- test_spec.lua local make_test = require 'test_helpers'.make_test describe('things', function() make_test(1, 2) make_test(4, 4) end) This is now possible by exposing the busted executor functions via `require 'busted'` so they can be imported by helper modules. --- busted.lua | 3 +++ busted/init.lua | 24 ++++++++++++++++++------ busted/runner.lua | 2 +- spec/executors_spec.lua | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 busted.lua create mode 100644 spec/executors_spec.lua diff --git a/busted.lua b/busted.lua new file mode 100644 index 00000000..917d21d8 --- /dev/null +++ b/busted.lua @@ -0,0 +1,3 @@ +-- This is a dummy file so it can be used in busted's specs +-- without adding ./?/init.lua to the lua path +return require 'busted.init' diff --git a/busted/init.lua b/busted/init.lua index 8ebf6b8b..6a32eef4 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -13,15 +13,15 @@ local function shuffle(t, seed) return t end -return function(busted) - local function remove(descriptors, element) - for _, descriptor in ipairs(descriptors) do - element.env[descriptor] = function(...) - error("'" .. descriptor .. "' not supported inside current context block", 2) - end +local function remove(descriptors, element) + for _, descriptor in ipairs(descriptors) do + element.env[descriptor] = function(...) + error("'" .. descriptor .. "' not supported inside current context block", 2) end end +end +local function init(busted) local function exec(descriptor, element) if not element.env then element.env = {} end @@ -201,3 +201,15 @@ return function(busted) return busted end + +return setmetatable({}, { + __call = function(self, busted) + init(busted) + + return setmetatable(self, { + __index = function(self, descriptor) + return busted.executors[descriptor] + end + }) + end +}) diff --git a/busted/runner.lua b/busted/runner.lua index fd53d64b..1cc5bae2 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -52,7 +52,7 @@ return function(options) local luacov = require 'busted.modules.luacov'() - require 'busted.init'(busted) + require 'busted'(busted) -- Default cli arg values local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' diff --git a/spec/executors_spec.lua b/spec/executors_spec.lua new file mode 100644 index 00000000..33762376 --- /dev/null +++ b/spec/executors_spec.lua @@ -0,0 +1,40 @@ + +describe('tests require "busted"', function() + local describe = describe + local context = context + local it = it + local pending = pending + local spec = spec + local test = test + local setup = setup + local teardown = teardown + local before_each = before_each + local after_each = after_each + + it('does not import init', function() + assert.is_nil(require 'busted'.init) + end) + + it('imports file executor', function() + assert.is_function(require 'busted'.file) + end) + + it('imports describe/it/pending', function() + assert.is_equal(describe, require 'busted'.describe) + assert.is_equal(it, require 'busted'.it) + assert.is_equal(pending, require 'busted'.pending) + end) + + it('imports aliases', function() + assert.is_equal(context, require 'busted'.context) + assert.is_equal(spec, require 'busted'.spec) + assert.is_equal(test, require 'busted'.test) + end) + + it('imports support functions', function() + assert.is_equal(setup, require 'busted'.setup) + assert.is_equal(teardown, require 'busted'.teardown) + assert.is_equal(before_each, require 'busted'.before_each) + assert.is_equal(after_each, require 'busted'.after_each) + end) +end) From 8636e68048dd1b9450ed7d55d8e75647cad314b7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 6 Jan 2015 13:35:44 -0800 Subject: [PATCH 078/293] Throw error on attempt to modify busted --- busted/init.lua | 4 ++++ spec/executors_spec.lua | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/busted/init.lua b/busted/init.lua index 6a32eef4..8fbf223d 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -209,6 +209,10 @@ return setmetatable({}, { return setmetatable(self, { __index = function(self, descriptor) return busted.executors[descriptor] + end, + + __newindex = function(self, key, value) + error('Attempt to modify busted') end }) end diff --git a/spec/executors_spec.lua b/spec/executors_spec.lua index 33762376..7f3f420f 100644 --- a/spec/executors_spec.lua +++ b/spec/executors_spec.lua @@ -37,4 +37,15 @@ describe('tests require "busted"', function() assert.is_equal(before_each, require 'busted'.before_each) assert.is_equal(after_each, require 'busted'.after_each) end) + + it('functions cannot be overwritten', function() + local foo = function() assert(false) end + assert.has_error(function() require 'busted'.it = foo end) + assert.is_equal(it, require 'busted'.it) + end) + + it('cannot add new fields', function() + local bar = function() assert(false) end + assert.has_error(function() require 'busted'.foo = bar end) + end) end) From f6536c2a95354743adb8a01a68c53f716377af21 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 12 Jan 2015 18:08:01 -0800 Subject: [PATCH 079/293] Add return statements to moonscript test case --- spec/moonscript_spec.moon | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/moonscript_spec.moon b/spec/moonscript_spec.moon index 938afe46..954827df 100644 --- a/spec/moonscript_spec.moon +++ b/spec/moonscript_spec.moon @@ -1,4 +1,6 @@ describe 'moonscript tests', -> it 'works', -> assert.are.equal true, true - + return + return +return From b3392fcf6288d1622bf4e9bcba629afce464c3f7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 12 Jan 2015 00:38:03 -0800 Subject: [PATCH 080/293] Apply tag filtering to describe and test aliases Fix tags for describe names by checking for tags using full test name instead of just the name of the current test block. Also apply tag filtering to test aliases. Fixes issue #323. --- busted/core.lua | 6 ++++++ busted/init.lua | 7 ++++--- busted/runner.lua | 49 +++++++++++++++++++++++++++++++++++++++-------- spec/cl_spec.lua | 18 ++++++++++++++--- spec/cl_tags.lua | 25 ++++++++++++++++++++++-- 5 files changed, 89 insertions(+), 16 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 758c60ad..ccebcdd8 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -214,6 +214,12 @@ return function() end) end + function busted.alias(alias, descriptor) + local publisher = busted.executors[descriptor] + busted.executors[alias] = publisher + environment.set(alias, publisher) + end + function busted.execute(current) if not current then current = busted.context.get() end for _, v in pairs(busted.context.children(current)) do diff --git a/busted/init.lua b/busted/init.lua index 8fbf223d..0c227984 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -178,11 +178,8 @@ local function init(busted) busted.register('file', file) busted.register('describe', describe) - busted.register('context', describe) busted.register('it', it) - busted.register('spec', it) - busted.register('test', it) busted.register('pending', pending) @@ -191,6 +188,10 @@ local function init(busted) busted.register('before_each') busted.register('after_each') + busted.alias('context', 'describe') + busted.alias('spec', 'it') + busted.alias('test', 'it') + assert = require 'luassert' spy = require 'luassert.spy' mock = require 'luassert.mock' diff --git a/busted/runner.lua b/busted/runner.lua index 1cc5bae2..6d632c66 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -226,33 +226,66 @@ return function(options) require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) end + local getFullName = function(name) + local parent = busted.context.get() + local names = { name } + + while parent and (parent.name or parent.descriptor) and + parent.descriptor ~= 'file' do + table.insert(names, 1, parent.name or parent.descriptor) + parent = busted.context.parent(parent) + end + + return table.concat(names, ' ') + end + local hasTag = function(name, tag) local found = name:find('#' .. tag) return (found ~= nil) end - local checkTags = function(name) + local filterExcludeTags = function(name) + local fullname = getFullName(name) for i, tag in pairs(excludeTags) do - if hasTag(name, tag) then + if hasTag(fullname, tag) then return nil, false end end + return nil, true + end + local filterTags = function(name) + local fullname = getFullName(name) for i, tag in pairs(tags) do - if hasTag(name, tag) then + if hasTag(fullname, tag) then return nil, true end end - return nil, (#tags == 0) end - if cliArgs.t ~= '' or cliArgs['exclude-tags'] ~= '' then - -- Watch for tags - busted.subscribe({ 'register', 'it' }, checkTags, { priority = 1 }) - busted.subscribe({ 'register', 'pending' }, checkTags, { priority = 1 }) + local filterOutNames = function(name) + local found = (getFullName(name):find(cliArgs['filter-out']) ~= nil) + return nil, not found end + local filterNames = function(name) + local found = (getFullName(name):find(cliArgs.filter) ~= nil) + return nil, found + end + + local filterIf = function(descriptors, fn, cond) + if cond then + for _, descriptor in ipairs(descriptors) do + busted.subscribe({ 'register', descriptor }, fn, { priority = 1 }) + end + end + end + + -- Note: filters are applied in reverse order + filterIf({ 'it', 'pending' }, filterTags, cliArgs.t ~= '') + filterIf({ 'it', 'pending' }, filterExcludeTags, cliArgs['exclude-tags'] ~= '') + -- Load test directory local rootFile = cliArgs.ROOT and normpath(path.join(fpath, cliArgs.ROOT)) or fileName local pattern = cliArgs.pattern diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 64da3266..9cfd808d 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -64,7 +64,7 @@ describe('Tests the busted command-line options', function() error_start() success, exitcode = execute('bin/busted --pattern=_tags.lua$') assert.is_false(success) - assert.is_equal(3, exitcode) + assert.is_equal(8, exitcode) success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag1') assert.is_false(success) assert.is_equal(2, exitcode) @@ -77,10 +77,10 @@ describe('Tests the busted command-line options', function() it('tests running with --exclude-tags specified', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --exclude-tags=tag1,tag2') + success, exitcode = execute('bin/busted --pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --exclude-tags=tag2') + success, exitcode = execute('bin/busted --pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') assert.is_false(success) assert.is_equal(2, exitcode) error_end() @@ -98,6 +98,18 @@ describe('Tests the busted command-line options', function() error_end() end) + it('tests running with --tags specified in describe', function () + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=dtag1') + assert.is_false(success) + assert.is_equal(4, exitcode) + success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=dtag2') + assert.is_false(success) + assert.is_equal(1, exitcode) + error_end() + end) + it('tests running with --lang specified', function() local success, exitcode error_start() diff --git a/spec/cl_tags.lua b/spec/cl_tags.lua index 269e64c6..cabb7ccb 100644 --- a/spec/cl_tags.lua +++ b/spec/cl_tags.lua @@ -7,12 +7,12 @@ describe('Tests the busted command-line options', function() error('error 1 on tag1') end) - it('is a test with a tag #tag1', function() + spec('is a test with a tag #tag1', function() -- works by counting failure error('error 2 on tag1') end) - it('is a test with a tag #tag2', function() + test('is a test with a tag #tag2', function() -- works by counting failure error('error on tag2') end) @@ -26,3 +26,24 @@ describe('Tests the busted command-line options', function() end) end) +describe('Tests describe with a tag #dtag1', function() + before_each(function() + error('error in before_each on dtag1') + end) + + after_each(function() + error('error in after_each on dtag1') + end) + + it('is a test inside describe', function() + end) + + it('is another test inside describe', function() + end) +end) + +context('Tests context with a tag #dtag2', function() + it('is a test inside context', function() + error('error on dtag2') + end) +end) From 06f69031ad78bbca7f282c7bc14f6622e570e92f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 12 Jan 2015 23:42:34 -0800 Subject: [PATCH 081/293] Add command-line option to filter by test name --- busted/runner.lua | 4 +++ completions/bash/busted.bash | 5 ++++ completions/zsh/_busted | 6 +++-- spec/cl_filter.lua | 49 ++++++++++++++++++++++++++++++++++++ spec/cl_spec.lua | 49 ++++++++++++++++++++++++++++++++++++ 5 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 spec/cl_filter.lua diff --git a/busted/runner.lua b/busted/runner.lua index 6d632c66..d4c97e1c 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -81,6 +81,8 @@ return function(options) cli:add_option('-d, --cwd=cwd', 'path to current working directory', './') cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags') cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags') + cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern') + cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter') cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) cli:add_option('-r, --run=RUN', 'config to run from .busted file') @@ -283,6 +285,8 @@ return function(options) end -- Note: filters are applied in reverse order + filterIf({ 'it', 'pending' }, filterNames, cliArgs.filter ~= '') + filterIf({ 'it', 'pending' }, filterOutNames, cliArgs['filter-out'] ~= '') filterIf({ 'it', 'pending' }, filterTags, cliArgs.t ~= '') filterIf({ 'it', 'pending' }, filterExcludeTags, cliArgs['exclude-tags'] ~= '') diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index fea4f21b..3e0820a6 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -93,6 +93,10 @@ _busted() { # no completion available return 0 ;; + --filter|--filter-out) + # no completion available + return 0 + ;; -m|--lpath|--cpath) _filedir -d return 0 @@ -118,6 +122,7 @@ _busted() { -t --tags= --exclude-tags= -m --lpath= --cpath= -r --run= + --filter= --filter-out= --repeat= --seed= --lang= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 72e56333..763bb472 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -24,8 +24,10 @@ _busted_args=( "(-p --pattern)"{-p,--pattern=}"[Only run test files matching the Lua pattern (default: _spec)]: :" "(-r --run)"{-r,--run=}"[Config to run from .busted file]:run configurations:->run" "(-s --enable-sound)"{-s,--enable-sound}"[Executes 'say' command if available]" -"(-t --tags --exclude-tags)"{-t,--tags=}"[Only run tests with these #tags]: :" -"(-t --tags --exclude-tags)--exclude-tags=[Do not run tests with these #tags, takes precedence over --tags]: :" +"(-t --tags)"{-t,--tags=}"[Only run tests with these #tags]: :" +"--exclude-tags=[Do not run tests with these #tags, takes precedence over --tags]: :" +"--filter=[Only run test names matching the Lua pattern]: :" +"--filter-out=[Do not run test names matching the Lua pattern, takes precedence over --filter]: :" "(-v --verbose)"{-v,--verbose}"[Verbose output of errors]" "*:files:_files" ) diff --git a/spec/cl_filter.lua b/spec/cl_filter.lua new file mode 100644 index 00000000..7973dcbe --- /dev/null +++ b/spec/cl_filter.lua @@ -0,0 +1,49 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Tests the busted command-line options', function() + + it('is a test with pattern1', function() + -- works by counting failure + error('error 1 on pattern1') + end) + + it('is another test with pattern1', function() + -- works by counting failure + error('error 2 on pattern1') + end) + + it('is a test with pattern2', function() + -- works by counting failure + error('error on pattern2') + end) + + it('is a test with pattern3', function() + -- nothing here, makes it succeed + end) + + it('is a test with two pattern3 and pattern4', function () + -- Always succeed + end) +end) + +describe('Tests describe with patt1', function() + before_each(function() + error('error in before_each on patt1') + end) + + after_each(function() + error('error in after_each on patt1') + end) + + it('is a test inside describe', function() + end) + + it('is another test inside describe', function() + end) +end) + +context('Tests context with patt2', function() + it('is a test inside context', function() + error('error on patt2') + end) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 9cfd808d..dbf17d12 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -110,6 +110,55 @@ describe('Tests the busted command-line options', function() error_end() end) + it('tests running with --filter specified', function () + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --pattern=_filter.lua$') + assert.is_false(success) + assert.is_equal(8, exitcode) + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern1"') + assert.is_false(success) + assert.is_equal(2, exitcode) + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern2"') + assert.is_false(success) + assert.is_equal(1, exitcode) + error_end() + end) + + it('tests running with --filter-out specified', function () + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter-out="pattern1"') + assert.is_false(success) + assert.is_equal(6, exitcode) + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter-out="pattern%d"') + assert.is_false(success) + assert.is_equal(5, exitcode) + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter-out="patt.*(%d)"') + assert.is_true(success) + error_end() + end) + + it('tests running with --filter and --filter-out specified', function () + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') + assert.is_true(success) + error_end() + end) + + it('tests running with --filter specified in describe', function () + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="patt1"') + assert.is_false(success) + assert.is_equal(4, exitcode) + success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="patt2"') + assert.is_false(success) + assert.is_equal(1, exitcode) + error_end() + end) + it('tests running with --lang specified', function() local success, exitcode error_start() From 15bd51c58a67ef31da1d69b28179d55db4e6a4bb Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 16 Jan 2015 13:20:39 -0800 Subject: [PATCH 082/293] Display errors/failures in order of execution This change updates the order that error, failure, and pending messages are displayed such that they are reported in the same order as when they occurred. Messages are still grouped according to their type, where all pending messages are grouped together, all failure messages are grouped together, etc. This allows for the same exact output messages to be displayed in the same order each time a test suite is executed with the same command-line options. --- busted/outputHandlers/base.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 75e0a147..c6d24ef3 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -101,7 +101,6 @@ return function(busted) local isError local insertTable - local id = tostring(element) if status == 'success' then insertTable = handler.successes @@ -118,16 +117,19 @@ return function(busted) isError = true end - insertTable[id] = handler.format(element, parent, element.message, debug, isError) + local formatted = handler.format(element, parent, element.message, debug, isError) + local id = tostring(element) if handler.inProgress[id] then for k, v in pairs(handler.inProgress[id]) do - insertTable[id][k] = v + formatted[k] = v end handler.inProgress[id] = nil end + table.insert(insertTable, formatted) + return nil, true end From beca2c7ff72c7d7abde7e7ef31d3f9825052c471 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 12 Jan 2015 23:43:08 -0800 Subject: [PATCH 083/293] Add command-line flag to list test names Add `--list` command-line option to list test names instead of running them. When printing a test name, pre-append the file name to the test name, and prevent support functions from being executed. --- busted/runner.lua | 18 ++++++++++++++++++ completions/bash/busted.bash | 1 + completions/zsh/_busted | 1 + spec/cl_list.lua | 12 ++++++++++++ spec/cl_spec.lua | 10 +++++++++- 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 spec/cl_list.lua diff --git a/busted/runner.lua b/busted/runner.lua index d4c97e1c..a92182ef 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -95,6 +95,7 @@ return function(options) cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') cli:add_flag('-v, --verbose', 'verbose output of errors') cli:add_flag('-s, --enable-sound', 'executes `say` command if available') + cli:add_flag('--list', 'list the names of all tests instead of running them') cli:add_flag('--randomize', 'force randomized test order') cli:add_flag('--shuffle', 'force randomized test order (alias for randomize)') cli:add_flag('--suppress-pending', 'suppress `pending` test output') @@ -276,6 +277,20 @@ return function(options) return nil, found end + local printNameOnly = function(name, fn, trace) + local fullname = getFullName(name) + if trace and trace.what == 'Lua' then + print(trace.short_src .. ': ' .. fullname) + else + print(fullname) + end + return nil, false + end + + local ignoreAll = function() + return nil, false + end + local filterIf = function(descriptors, fn, cond) if cond then for _, descriptor in ipairs(descriptors) do @@ -284,6 +299,9 @@ return function(options) end end + filterIf({ 'it', 'pending' }, printNameOnly, cliArgs.list) + filterIf({ 'setup', 'teardown', 'before_each', 'after_each' }, ignoreAll, cliArgs.list) + -- Note: filters are applied in reverse order filterIf({ 'it', 'pending' }, filterNames, cliArgs.filter ~= '') filterIf({ 'it', 'pending' }, filterOutNames, cliArgs['filter-out'] ~= '') diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 3e0820a6..3a40a573 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -116,6 +116,7 @@ _busted() { -h --help -v --verbose --version + --list -o --output= -p --pattern= -d --cwd= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 763bb472..fd725104 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -14,6 +14,7 @@ _busted_args=( "(--randomize --shuffle)--shuffle[Force randomized test order (alias for --randomize)]" "--suppress-pending[Suppress 'pending' test output]" "--version[Prints the program version and exits]" +"--list[List the names of all tests instead of running them]" "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" "(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" diff --git a/spec/cl_list.lua b/spec/cl_list.lua new file mode 100644 index 00000000..c376ce45 --- /dev/null +++ b/spec/cl_list.lua @@ -0,0 +1,12 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Tests list', function() + it('test 1', function() + end) + + it('test 2', function() + end) + + it('test 3', function() + end) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index dbf17d12..7e67a835 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -159,6 +159,15 @@ describe('Tests the busted command-line options', function() error_end() end) + it('tests running with --list specified', function() + local result = run('bin/busted --list --pattern=cl_list.lua$') + local list = result:match('(.-\n)\n') + local expected = './spec/cl_list.lua: Tests list test 1\n' .. + './spec/cl_list.lua: Tests list test 2\n' .. + './spec/cl_list.lua: Tests list test 3\n' + assert.is_equal(expected, list) + end) + it('tests running with --lang specified', function() local success, exitcode error_start() @@ -224,7 +233,6 @@ describe('Tests the busted command-line options', function() error_end() end) - end) describe('Tests failing tests through the commandline', function() From f064188fcdcb8f83b1e1176577ab640466dc2f55 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 14 Jan 2015 12:46:07 -0800 Subject: [PATCH 084/293] Do not display test status when --list is enabled --- busted/runner.lua | 8 ++++++-- spec/cl_spec.lua | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index a92182ef..704de256 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -299,8 +299,12 @@ return function(options) end end - filterIf({ 'it', 'pending' }, printNameOnly, cliArgs.list) - filterIf({ 'setup', 'teardown', 'before_each', 'after_each' }, ignoreAll, cliArgs.list) + if cliArgs.list then + busted.subscribe({ 'suite', 'start' }, ignoreAll, { priority = 1 }) + busted.subscribe({ 'suite', 'end' }, ignoreAll, { priority = 1 }) + filterIf({ 'setup', 'teardown', 'before_each', 'after_each' }, ignoreAll, true) + filterIf({ 'it', 'pending' }, printNameOnly, true) + end -- Note: filters are applied in reverse order filterIf({ 'it', 'pending' }, filterNames, cliArgs.filter ~= '') diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 7e67a835..2ea5f4b1 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -161,11 +161,10 @@ describe('Tests the busted command-line options', function() it('tests running with --list specified', function() local result = run('bin/busted --list --pattern=cl_list.lua$') - local list = result:match('(.-\n)\n') local expected = './spec/cl_list.lua: Tests list test 1\n' .. './spec/cl_list.lua: Tests list test 2\n' .. './spec/cl_list.lua: Tests list test 3\n' - assert.is_equal(expected, list) + assert.is_equal(expected, result) end) it('tests running with --lang specified', function() From d253a94a0d790f673e058a33aef31cf1615856b5 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 14 Jan 2015 13:26:44 -0800 Subject: [PATCH 085/293] Update --list to print line number of test --- busted/runner.lua | 2 +- spec/cl_spec.lua | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 704de256..91d84d7b 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -280,7 +280,7 @@ return function(options) local printNameOnly = function(name, fn, trace) local fullname = getFullName(name) if trace and trace.what == 'Lua' then - print(trace.short_src .. ': ' .. fullname) + print(trace.short_src .. ':' .. trace.currentline .. ': ' .. fullname) else print(fullname) end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 2ea5f4b1..6047c751 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -161,9 +161,9 @@ describe('Tests the busted command-line options', function() it('tests running with --list specified', function() local result = run('bin/busted --list --pattern=cl_list.lua$') - local expected = './spec/cl_list.lua: Tests list test 1\n' .. - './spec/cl_list.lua: Tests list test 2\n' .. - './spec/cl_list.lua: Tests list test 3\n' + local expected = './spec/cl_list.lua:4: Tests list test 1\n' .. + './spec/cl_list.lua:7: Tests list test 2\n' .. + './spec/cl_list.lua:10: Tests list test 3\n' assert.is_equal(expected, result) end) From c84abb8dc6e071674d9ed82d0982b6ff6a8a33c2 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 14 Jan 2015 13:03:25 -0800 Subject: [PATCH 086/293] Refactor how test filters are applied --- busted/runner.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 91d84d7b..ad36276e 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -291,8 +291,8 @@ return function(options) return nil, false end - local filterIf = function(descriptors, fn, cond) - if cond then + local applyFilter = function(descriptors, name, fn) + if cliArgs[name] and cliArgs[name] ~= '' then for _, descriptor in ipairs(descriptors) do busted.subscribe({ 'register', descriptor }, fn, { priority = 1 }) end @@ -302,15 +302,15 @@ return function(options) if cliArgs.list then busted.subscribe({ 'suite', 'start' }, ignoreAll, { priority = 1 }) busted.subscribe({ 'suite', 'end' }, ignoreAll, { priority = 1 }) - filterIf({ 'setup', 'teardown', 'before_each', 'after_each' }, ignoreAll, true) - filterIf({ 'it', 'pending' }, printNameOnly, true) + applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'list', ignoreAll) + applyFilter({ 'it', 'pending' }, 'list', printNameOnly) end - -- Note: filters are applied in reverse order - filterIf({ 'it', 'pending' }, filterNames, cliArgs.filter ~= '') - filterIf({ 'it', 'pending' }, filterOutNames, cliArgs['filter-out'] ~= '') - filterIf({ 'it', 'pending' }, filterTags, cliArgs.t ~= '') - filterIf({ 'it', 'pending' }, filterExcludeTags, cliArgs['exclude-tags'] ~= '') + -- The following filters are applied in reverse order + applyFilter({ 'it', 'pending' }, 'filter' , filterNames ) + applyFilter({ 'it', 'pending' }, 'filter-out' , filterOutNames ) + applyFilter({ 'it', 'pending' }, 'tags' , filterTags ) + applyFilter({ 'it', 'pending' }, 'exclude-tags', filterExcludeTags) -- Load test directory local rootFile = cliArgs.ROOT and normpath(path.join(fpath, cliArgs.ROOT)) or fileName From 1b17985acc45a727909a03e985903e482f24216f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 15 Jan 2015 12:43:56 -0800 Subject: [PATCH 087/293] Do not execute describe if it is filtered out This prevents describes that have been filtered out, with the --exclude-tags or --filter-out options, from running any setup or teardown functions. --- busted/runner.lua | 11 +++++------ spec/cl_filter.lua | 4 ++-- spec/cl_spec.lua | 16 ++++++++-------- spec/cl_tags.lua | 4 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index ad36276e..f0661973 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -248,9 +248,8 @@ return function(options) end local filterExcludeTags = function(name) - local fullname = getFullName(name) for i, tag in pairs(excludeTags) do - if hasTag(fullname, tag) then + if hasTag(name, tag) then return nil, false end end @@ -307,10 +306,10 @@ return function(options) end -- The following filters are applied in reverse order - applyFilter({ 'it', 'pending' }, 'filter' , filterNames ) - applyFilter({ 'it', 'pending' }, 'filter-out' , filterOutNames ) - applyFilter({ 'it', 'pending' }, 'tags' , filterTags ) - applyFilter({ 'it', 'pending' }, 'exclude-tags', filterExcludeTags) + applyFilter({ 'it', 'pending' } , 'filter' , filterNames ) + applyFilter({ 'describe', 'it', 'pending' }, 'filter-out' , filterOutNames ) + applyFilter({ 'it', 'pending' } , 'tags' , filterTags ) + applyFilter({ 'describe', 'it', 'pending' }, 'exclude-tags', filterExcludeTags) -- Load test directory local rootFile = cliArgs.ROOT and normpath(path.join(fpath, cliArgs.ROOT)) or fileName diff --git a/spec/cl_filter.lua b/spec/cl_filter.lua index 7973dcbe..57fd6aa6 100644 --- a/spec/cl_filter.lua +++ b/spec/cl_filter.lua @@ -43,7 +43,7 @@ describe('Tests describe with patt1', function() end) context('Tests context with patt2', function() - it('is a test inside context', function() - error('error on patt2') + setup(function() + error('error in setup on patt2') end) end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 6047c751..37f5dbfa 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -67,10 +67,10 @@ describe('Tests the busted command-line options', function() assert.is_equal(8, exitcode) success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag1') assert.is_false(success) - assert.is_equal(2, exitcode) + assert.is_equal(3, exitcode) success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag1,tag2') assert.is_false(success) - assert.is_equal(3, exitcode) + assert.is_equal(4, exitcode) error_end() end) @@ -93,8 +93,8 @@ describe('Tests the busted command-line options', function() assert.is_false(success) assert.is_equal(1, exitcode) success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') - assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_false(success) + assert.is_equal(1, exitcode) error_end() end) @@ -103,7 +103,7 @@ describe('Tests the busted command-line options', function() error_start() success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=dtag1') assert.is_false(success) - assert.is_equal(4, exitcode) + assert.is_equal(5, exitcode) success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=dtag2') assert.is_false(success) assert.is_equal(1, exitcode) @@ -118,10 +118,10 @@ describe('Tests the busted command-line options', function() assert.is_equal(8, exitcode) success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern1"') assert.is_false(success) - assert.is_equal(2, exitcode) + assert.is_equal(3, exitcode) success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern2"') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(2, exitcode) error_end() end) @@ -152,7 +152,7 @@ describe('Tests the busted command-line options', function() error_start() success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="patt1"') assert.is_false(success) - assert.is_equal(4, exitcode) + assert.is_equal(5, exitcode) success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="patt2"') assert.is_false(success) assert.is_equal(1, exitcode) diff --git a/spec/cl_tags.lua b/spec/cl_tags.lua index cabb7ccb..0aeb6fed 100644 --- a/spec/cl_tags.lua +++ b/spec/cl_tags.lua @@ -43,7 +43,7 @@ describe('Tests describe with a tag #dtag1', function() end) context('Tests context with a tag #dtag2', function() - it('is a test inside context', function() - error('error on dtag2') + setup(function() + error('error in setup on dtag2') end) end) From 230b640ac2160ba19d18746b29e7abc92b350d4e Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 15 Jan 2015 16:35:41 -0800 Subject: [PATCH 088/293] Remove unused require from moonscript.lua --- busted/modules/files/moonscript.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/busted/modules/files/moonscript.lua b/busted/modules/files/moonscript.lua index ba428c3d..5973c929 100644 --- a/busted/modules/files/moonscript.lua +++ b/busted/modules/files/moonscript.lua @@ -1,5 +1,3 @@ -local utils = require 'pl.utils' - local ok, moonscript, line_tables, util = pcall(function() return require 'moonscript', require 'moonscript.line_tables', require 'moonscript.util' end) From 1a46685129f3f0e4204f2c710aff1530c915220c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 15 Jan 2015 16:51:21 -0800 Subject: [PATCH 089/293] Move utility functions into busted/utils.lua --- busted-2.0.rc5-0.rockspec | 1 + busted/init.lua | 13 +--------- busted/runner.lua | 39 +++--------------------------- busted/utils.lua | 51 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 48 deletions(-) create mode 100644 busted/utils.lua diff --git a/busted-2.0.rc5-0.rockspec b/busted-2.0.rc5-0.rockspec index bf8da55d..7a2911d5 100644 --- a/busted-2.0.rc5-0.rockspec +++ b/busted-2.0.rc5-0.rockspec @@ -38,6 +38,7 @@ build = { ['busted.done'] = 'busted/done.lua', ['busted.runner'] = 'busted/runner.lua', ['busted.status'] = 'busted/status.lua', + ['busted.utils'] = 'busted/utils.lua', ['busted.init'] = 'busted/init.lua', ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', diff --git a/busted/init.lua b/busted/init.lua index 0c227984..4eabb8f5 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -1,17 +1,6 @@ local unpack = require 'busted.compatibility'.unpack +local shuffle = require 'busted.utils'.shuffle -math.randomseed(os.time()) - -local function shuffle(t, seed) - if seed then math.randomseed(seed) end - local n = #t - while n >= 2 do - local k = math.random(n) - t[n], t[k] = t[k], t[n] - n = n - 1 - end - return t -end local function remove(descriptors, element) for _, descriptor in ipairs(descriptors) do diff --git a/busted/runner.lua b/busted/runner.lua index f0661973..e8d19458 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -3,42 +3,9 @@ local getfenv = require 'busted.compatibility'.getfenv local setfenv = require 'busted.compatibility'.setfenv local path = require 'pl.path' -local utils = require 'pl.utils' +local utils = require 'busted.utils' local loaded = false --- Do not use pl.path.normpath --- It is broken for paths with leading '../../' -local function normpath(fpath) - if type(fpath) ~= 'string' then - error(fpath .. ' is not a string') - end - local sep = '/' - if path.is_windows then - sep = '\\' - if fpath:match '^\\\\' then -- UNC - return '\\\\' .. normpath(fpath:sub(3)) - end - fpath = fpath:gsub('/','\\') - end - local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' - local np_pat1 = np_gen1:gsub('SEP', sep) - local np_pat2 = np_gen2:gsub('SEP', sep) - local k - repeat -- /./ -> / - fpath, k = fpath:gsub(np_pat2, sep) - until k == 0 - repeat -- A/../ -> (empty) - local oldpath = fpath - fpath, k = fpath:gsub(np_pat1, function(d, up) - if d == '..' then return nil end - if d == '.' then return up end - return '' - end) - until k == 0 or oldpath == fpath - if fpath == '' then fpath = '.' end - return fpath -end - return function(options) if loaded then return else loaded = true end @@ -118,7 +85,7 @@ return function(options) -- Load busted config file if available local configFile = { } - local bustedConfigFilePath = normpath(path.join(fpath, '.busted')) + local bustedConfigFilePath = utils.normpath(path.join(fpath, '.busted')) local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) @@ -312,7 +279,7 @@ return function(options) applyFilter({ 'describe', 'it', 'pending' }, 'exclude-tags', filterExcludeTags) -- Load test directory - local rootFile = cliArgs.ROOT and normpath(path.join(fpath, cliArgs.ROOT)) or fileName + local rootFile = cliArgs.ROOT and utils.normpath(path.join(fpath, cliArgs.ROOT)) or fileName local pattern = cliArgs.pattern local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) local fileList = testFileLoader(rootFile, pattern) diff --git a/busted/utils.lua b/busted/utils.lua new file mode 100644 index 00000000..5f67b1ac --- /dev/null +++ b/busted/utils.lua @@ -0,0 +1,51 @@ +local path = require 'pl.path' + +math.randomseed(os.time()) + +return { + split = require 'pl.utils'.split, + + -- Do not use pl.path.normpath + -- It is broken for paths with leading '../../' + normpath = function(fpath) + if type(fpath) ~= 'string' then + error(fpath .. ' is not a string') + end + local sep = '/' + if path.is_windows then + sep = '\\' + if fpath:match '^\\\\' then -- UNC + return '\\\\' .. normpath(fpath:sub(3)) + end + fpath = fpath:gsub('/','\\') + end + local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' + local np_pat1 = np_gen1:gsub('SEP', sep) + local np_pat2 = np_gen2:gsub('SEP', sep) + local k + repeat -- /./ -> / + fpath, k = fpath:gsub(np_pat2, sep) + until k == 0 + repeat -- A/../ -> (empty) + local oldpath = fpath + fpath, k = fpath:gsub(np_pat1, function(d, up) + if d == '..' then return nil end + if d == '.' then return up end + return '' + end) + until k == 0 or oldpath == fpath + if fpath == '' then fpath = '.' end + return fpath + end, + + shuffle = function(t, seed) + if seed then math.randomseed(seed) end + local n = #t + while n >= 2 do + local k = math.random(n) + t[n], t[k] = t[k], t[n] + n = n - 1 + end + return t + end +} From 12b9ed013cce7709100502c351a816c352637d57 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 15 Jan 2015 18:09:51 -0800 Subject: [PATCH 090/293] Add command-line flags to sort/shuffle file order Add flags to sort or shuffle file execution order. Also, allow tests within a file to be sorted by name. --- busted/init.lua | 13 ++++++++++ busted/modules/test_file_loader.lua | 11 ++++++-- busted/runner.lua | 21 ++++++++++++--- completions/bash/busted.bash | 3 ++- completions/zsh/_busted | 8 ++++-- spec/cl_randomize.lua | 2 +- spec/cl_sort.lua | 29 +++++++++++++++++++++ spec/cl_spec.lua | 40 +++++++++++++++++------------ 8 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 spec/cl_sort.lua diff --git a/busted/init.lua b/busted/init.lua index 4eabb8f5..400399a2 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -1,6 +1,15 @@ local unpack = require 'busted.compatibility'.unpack local shuffle = require 'busted.utils'.shuffle +local function sort(elements) + table.sort(elements, function(t1, t2) + if t1.name and t2.name then + return t1.name < t2.name + end + return t2.name ~= nil + end) + return elements +end local function remove(descriptors, element) for _, descriptor in ipairs(descriptors) do @@ -84,6 +93,8 @@ local function init(busted) if randomize then file.randomseed = busted.randomseed shuffle(busted.context.children(file), busted.randomseed) + elseif busted.sort then + sort(busted.context.children(file)) end if execAll('setup', file) then busted.execute(file) @@ -108,6 +119,8 @@ local function init(busted) if randomize then describe.randomseed = busted.randomseed shuffle(busted.context.children(describe), busted.randomseed) + elseif busted.sort then + sort(busted.context.children(describe)) end if execAll('setup', describe) then busted.execute(describe) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 5f2159b4..0a4ae89c 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -1,7 +1,8 @@ -return function(busted, loaders) +return function(busted, loaders, options) local path = require 'pl.path' local dir = require 'pl.dir' local tablex = require 'pl.tablex' + local shuffle = require 'busted.utils'.shuffle local fileLoaders = {} for _, v in pairs(loaders) do @@ -48,7 +49,13 @@ return function(busted, loaders) local loadTestFiles = function(rootFile, pattern, loaders) local fileList = getTestFiles(rootFile, pattern) - for i, fileName in pairs(fileList) do + if options.shuffle then + shuffle(fileList, options.seed) + elseif options.sort then + table.sort(fileList) + end + + for i, fileName in ipairs(fileList) do local testFile, getTrace, rewriteMessage = loadTestFile(busted, fileName, loaders) if testFile then diff --git a/busted/runner.lua b/busted/runner.lua index e8d19458..30f3845e 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -63,8 +63,12 @@ return function(options) cli:add_flag('-v, --verbose', 'verbose output of errors') cli:add_flag('-s, --enable-sound', 'executes `say` command if available') cli:add_flag('--list', 'list the names of all tests instead of running them') - cli:add_flag('--randomize', 'force randomized test order') - cli:add_flag('--shuffle', 'force randomized test order (alias for randomize)') + cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)') + cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files') + cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests') + cli:add_flag('--sort', 'sort file and test order (--sort-tests and --sort-files)') + cli:add_flag('--sort-files', 'sort file execution order') + cli:add_flag('--sort-tests', 'sort test order within a file') cli:add_flag('--suppress-pending', 'suppress `pending` test output') cli:add_flag('--defer-print', 'defer print to when test suite is complete') @@ -174,7 +178,8 @@ return function(options) end) -- Set up randomization options - busted.randomize = cliArgs.randomize or cliArgs.shuffle + busted.sort = cliArgs['sort-tests'] or cliArgs.sort + busted.randomize = cliArgs['shuffle-tests'] or cliArgs.shuffle busted.randomseed = tonumber(cliArgs.seed) or os.time() if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then print('Argument to --seed must be a number') @@ -278,10 +283,18 @@ return function(options) applyFilter({ 'it', 'pending' } , 'tags' , filterTags ) applyFilter({ 'describe', 'it', 'pending' }, 'exclude-tags', filterExcludeTags) + -- Set up test loader options + local testFileLoaderOptions = { + verbose = cliArgs.verbose, + sort = cliArgs['sort-files'] or cliArgs.sort, + shuffle = cliArgs['shuffle-files'] or cliArgs.shuffle, + seed = busted.randomseed + } + -- Load test directory local rootFile = cliArgs.ROOT and utils.normpath(path.join(fpath, cliArgs.ROOT)) or fileName local pattern = cliArgs.pattern - local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders) + local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders, testFileLoaderOptions) local fileList = testFileLoader(rootFile, pattern) if #fileList == 0 then print('No test files found matching Lua pattern: ' .. pattern) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 3a40a573..bc99f259 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -131,7 +131,8 @@ _busted() { --helper= -c --coverage -s --enable-sound - --randomize --shuffle + --shuffle --shuffle-tests --shuffle-files + --sort --sort-tests --sort-files --supress-pending --defer-print" compopt -o nospace diff --git a/completions/zsh/_busted b/completions/zsh/_busted index fd725104..82104904 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -10,8 +10,12 @@ _busted_args=( "--lang=[Language for error messages (default: en)]:languages:(ar de en fr ja nl ru th ua zh)" "--repeat=[Run the tests repeatedly (default: 1)]: :" "--seed=[Random seed value to use for shuffing test order (default: os.time())]: :" -"(--randomize --shuffle)--randomize[Force randomized test order]" -"(--randomize --shuffle)--shuffle[Force randomized test order (alias for --randomize)]" +"(--sort --shuffle)--shuffle[Randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)]" +"(--sort-files --shuffle-files)--shuffle-files[Randomize file execution order, takes precedence over --sort-files]" +"(--sort-tests --shuffle-tests)--shuffle-tests[Randomize test order within a file, takes precedence over --sort-tests]" +"(--sort --shuffle)--sort[Sort file and test order (--sort-tests and --sort-files)]" +"(--sort-files --shuffle-files)--sort-files[Sort file execution order]" +"(--sort-tests --shuffle-tests)--sort-tests[Sort test order within a file]" "--suppress-pending[Suppress 'pending' test output]" "--version[Prints the program version and exits]" "--list[List the names of all tests instead of running them]" diff --git a/spec/cl_randomize.lua b/spec/cl_randomize.lua index 5a811214..91e933b3 100644 --- a/spec/cl_randomize.lua +++ b/spec/cl_randomize.lua @@ -2,7 +2,7 @@ local unexpected = {} local order = {} -describe('Randomizing test order with --randomize flag', function() +describe('Randomizing test order with --shuffle flag', function() for i = 1, 100 do table.insert(unexpected, i) diff --git a/spec/cl_sort.lua b/spec/cl_sort.lua new file mode 100644 index 00000000..68ddfc92 --- /dev/null +++ b/spec/cl_sort.lua @@ -0,0 +1,29 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Randomizing test order with --sort flag', function() + local expected = {} + local scratch = {} + local order = {} + + for i = 1, 100 do + table.insert(expected, i) + table.insert(scratch, i) + end + + while #scratch > 0 do + local n = #scratch + local k = math.random(n) + local num = scratch[k] + + it(string.format('test number %03d', num), function() + table.insert(order, num) + end) + + scratch[k], scratch[n] = scratch[n], scratch[k] + table.remove(scratch) + end + + teardown('runs tests in sorted order', function() + assert.are.same(expected, order) + end) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 37f5dbfa..b7171fdf 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -588,24 +588,30 @@ describe('Tests random seed through the commandline', function() end) end) -describe('Tests randomize/shuffle commandline option', function() - it('forces test shuffling for non-randomized tests', function() - local success, exitcode - error_start() - success, exitcode = execute('bin/busted --shuffle --pattern=cl_randomize.lua$') - assert.is_true(success) - assert.is_equal(0, exitcode) - error_end() - end) +describe('Tests shuffle commandline option', function() + for _, opt in ipairs({ '--shuffle', '--shuffle-tests' }) do + it('forces test shuffling for non-randomized tests, ' .. opt, function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted ' .. opt .. ' --pattern=cl_randomize.lua$') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) + end +end) - it('forces test randomization for non-randomized tests', function() - local success, exitcode - error_start() - success, exitcode = execute('bin/busted --randomize --pattern=cl_randomize.lua$') - assert.is_true(success) - assert.is_equal(0, exitcode) - error_end() - end) +describe('Tests sort commandline option', function() + for _, opt in ipairs({ '--sort', '--sort-tests' }) do + it('sorts tests by name, ' .. opt, function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted ' .. opt .. ' --pattern=cl_sort.lua$') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) + end end) describe('Tests repeat commandline option', function() From 1bead4ca36103f56f7c30c7a6d5b09d93a0af790 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 20 Jan 2015 22:59:00 -0800 Subject: [PATCH 091/293] Add --no-keep-going commaind-line flag Add command-line flag to quit after first failure or error is encountered. --- busted/core.lua | 2 +- busted/runner.lua | 15 +++++++++++++++ completions/bash/busted.bash | 1 + completions/zsh/_busted | 1 + spec/cl_spec.lua | 11 +++++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/busted/core.lua b/busted/core.lua index ccebcdd8..6d1b99dd 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -224,7 +224,7 @@ return function() if not current then current = busted.context.get() end for _, v in pairs(busted.context.children(current)) do local executor = executors[v.descriptor] - if executor then + if executor and not busted.skipAll then busted.safe(v.descriptor, function() executor(v) end, v) end end diff --git a/busted/runner.lua b/busted/runner.lua index 30f3845e..72235a7f 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -62,6 +62,7 @@ return function(options) cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') cli:add_flag('-v, --verbose', 'verbose output of errors') cli:add_flag('-s, --enable-sound', 'executes `say` command if available') + cli:add_flag('--no-keep-going', 'quit after first error or failure') cli:add_flag('--list', 'list the names of all tests instead of running them') cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)') cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files') @@ -159,12 +160,14 @@ return function(options) -- watch for test errors local failures = 0 local errors = 0 + local quitOnError = cliArgs['no-keep-going'] busted.subscribe({ 'error' }, function(element, parent, status) if element.descriptor == 'output' then print('Cannot load output library: ' .. element.name) end errors = errors + 1 + busted.skipAll = quitOnError return nil, true end) @@ -174,6 +177,7 @@ return function(options) else errors = errors + 1 end + busted.skipAll = quitOnError return nil, true end) @@ -262,6 +266,10 @@ return function(options) return nil, false end + local skipOnError = function() + return nil, (failures == 0 and errors == 0) + end + local applyFilter = function(descriptors, name, fn) if cliArgs[name] and cliArgs[name] ~= '' then for _, descriptor in ipairs(descriptors) do @@ -277,6 +285,9 @@ return function(options) applyFilter({ 'it', 'pending' }, 'list', printNameOnly) end + applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'no-keep-going', skipOnError) + applyFilter({ 'file', 'describe', 'it', 'pending' }, 'no-keep-going', skipOnError) + -- The following filters are applied in reverse order applyFilter({ 'it', 'pending' } , 'filter' , filterNames ) applyFilter({ 'describe', 'it', 'pending' }, 'filter-out' , filterOutNames ) @@ -341,6 +352,10 @@ return function(options) busted.publish({ 'suite', 'start' }) busted.execute() busted.publish({ 'suite', 'end' }) + + if quitOnError and (failures > 0 or errors > 0) then + break + end end local exit = 0 diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index bc99f259..0173584f 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -131,6 +131,7 @@ _busted() { --helper= -c --coverage -s --enable-sound + --no-keep-going --shuffle --shuffle-tests --shuffle-files --sort --sort-tests --sort-files --supress-pending diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 82104904..4c572851 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -19,6 +19,7 @@ _busted_args=( "--suppress-pending[Suppress 'pending' test output]" "--version[Prints the program version and exits]" "--list[List the names of all tests instead of running them]" +"--no-keep-going[Quit after first error or failure]" "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" "(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index b7171fdf..54600529 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -624,3 +624,14 @@ describe('Tests repeat commandline option', function() error_end() end) end) + +describe('Tests no-keep-going commandline option', function() + it('skips all tests after first error', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --no-keep-going --pattern=cl_two_failures.lua$') + assert.is_false(success) + assert.is_equal(1, exitcode) + error_end() + end) +end) From 1b08c8b6b587efea355de2738eef64b2f8f6950f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 7 Feb 2015 16:13:49 -0800 Subject: [PATCH 092/293] Use `wget` in travis setup Switch to using `wget` instead of `curl` in travis setup so that site redirection will work when downloading source packages to install. --- .travis_setup.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis_setup.sh b/.travis_setup.sh index 16b02769..bf6e7090 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -9,22 +9,22 @@ echo 'rocks_servers = { if [ "$LUA" == "LuaJIT 2.0" ]; then - curl http://luajit.org/download/LuaJIT-2.0.2.tar.gz | tar xz + wget -O - http://luajit.org/download/LuaJIT-2.0.2.tar.gz | tar xz cd LuaJIT-2.0.2 make && sudo make install INSTALL_TSYMNAME=lua; else if [ "$LUA" == "Lua 5.1" ]; then - curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz + wget -O - http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz cd lua-5.1.5; elif [ "$LUA" == "Lua 5.2" ]; then - curl http://www.lua.org/ftp/lua-5.2.3.tar.gz | tar xz + wget -O - http://www.lua.org/ftp/lua-5.2.3.tar.gz | tar xz cd lua-5.2.3; fi sudo make linux install; fi cd .. -curl http://luarocks.org/releases/luarocks-2.1.2.tar.gz | tar xz +wget -O - http://luarocks.org/releases/luarocks-2.1.2.tar.gz | tar xz cd luarocks-2.1.2 if [ "$LUA" == "LuaJIT 2.0" ]; then From 51d5c51d87cac83d89baf816a055b02aa34e9c60 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 7 Feb 2015 16:46:19 -0800 Subject: [PATCH 093/293] Update travis to use luarocks v2.2.0 --- .travis_setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis_setup.sh b/.travis_setup.sh index bf6e7090..5d414420 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -24,8 +24,8 @@ else fi cd .. -wget -O - http://luarocks.org/releases/luarocks-2.1.2.tar.gz | tar xz -cd luarocks-2.1.2 +wget -O - http://luarocks.org/releases/luarocks-2.2.0.tar.gz | tar xz +cd luarocks-2.2.0 if [ "$LUA" == "LuaJIT 2.0" ]; then ./configure --with-lua-include=/usr/local/include/luajit-2.0; From 0ba39befa459b31518ea8884b8025f5cbd74572b Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 7 Feb 2015 16:56:13 -0800 Subject: [PATCH 094/293] Update travis setup script to exit on error --- .travis_setup.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis_setup.sh b/.travis_setup.sh index 5d414420..4982fdbf 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -2,6 +2,8 @@ # Sets up Lua and Luarocks. # LUA must be "Lua 5.1", "Lua 5.2" or "LuaJIT 2.0". +set -e + echo 'rocks_servers = { "http://rocks.moonscript.org/", "http://luarocks.org/repositories/rocks" From 8592abeaaa83b1a9b305446e61ce890a1212afc6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 2 Feb 2015 17:24:01 -0800 Subject: [PATCH 095/293] Support loading output handler via Lua search path This allows an output handler to be loaded from a module found in the Lua search path. The output handler can still be loaded from a lua or moonscript file as well. If the output handler specified on the command line cannot be found in `busted/outputHandlers/`, then attempt to load the output handler as if it were in the Lua module search path. --- busted/modules/output_handler_loader.lua | 8 ++++++-- spec/cl_spec.lua | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index fcbceb43..44808be3 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -8,13 +8,17 @@ return function() if output:match('.lua$') or output:match('.moon$') then handler = loadfile(path.normpath(opath))() else - handler = require('busted.outputHandlers.'..output) + handler = require('busted.outputHandlers.' .. output) end end) + if not success then + success, err = pcall(function() handler = require(output) end) + end + if not success then busted.publish({ 'error', 'output' }, { descriptor = 'output', name = output }, nil, err, {}) - handler = require('busted.outputHandlers.'..defaultOutput) + handler = require('busted.outputHandlers.' .. defaultOutput) end return handler(options, busted) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 54600529..3a8e9b94 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -223,6 +223,15 @@ describe('Tests the busted command-line options', function() error_end() end) + it('tests running with --output specified with module in lua path', function() + local success, exitcode + error_start() + success, exitcode = execute('bin/busted --pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') + assert.is_true(success) + assert.is_equal(0, exitcode) + error_end() + end) + it('tests no tests to exit with a fail-exitcode', function() local success, exitcode error_start() From 53c9d413c77a7491971ed4ace357f0ffda2eab7d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 6 Feb 2015 00:09:49 -0800 Subject: [PATCH 096/293] Fix bad Lua path This fixes an issue with using --lpath when --cwd is also specified. If the path specified by --cwd does not end with a path separator, then the path prepended to the Lua path becomes malformed. --- busted/runner.lua | 10 +++++----- spec/cl_lua_path.lua | 8 ++++++++ spec/cl_spec.lua | 7 +++++++ spec/cl_test_module.lua | 1 + 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 spec/cl_lua_path.lua create mode 100644 spec/cl_test_module.lua diff --git a/busted/runner.lua b/busted/runner.lua index 72235a7f..ac35bcaa 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -86,7 +86,7 @@ return function(options) end -- Load current working directory - local fpath = cliArgs.d + local fpath = utils.normpath(cliArgs.d) -- Load busted config file if available local configFile = { } @@ -123,15 +123,15 @@ return function(options) -- Add additional package paths based on lpath and cpath cliArgs if #cliArgs.lpath > 0 then lpathprefix = cliArgs.lpath - lpathprefix = lpathprefix:gsub('^%.[/%\\]', fpath ) - lpathprefix = lpathprefix:gsub(';%.[/%\\]', ';' .. fpath) + lpathprefix = lpathprefix:gsub('^%.([/%\\])', fpath .. '%1') + lpathprefix = lpathprefix:gsub(';%.([/%\\])', ';' .. fpath .. '%1') package.path = (lpathprefix .. ';' .. package.path):gsub(';;',';') end if #cliArgs.cpath > 0 then cpathprefix = cliArgs.cpath - cpathprefix = cpathprefix:gsub('^%.[/%\\]', fpath ) - cpathprefix = cpathprefix:gsub(';%.[/%\\]', ';' .. fpath) + cpathprefix = cpathprefix:gsub('^%.([/%\\])', fpath .. '%1') + cpathprefix = cpathprefix:gsub(';%.([/%\\])', ';' .. fpath .. '%1') package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') end diff --git a/spec/cl_lua_path.lua b/spec/cl_lua_path.lua new file mode 100644 index 00000000..30ec6f8f --- /dev/null +++ b/spec/cl_lua_path.lua @@ -0,0 +1,8 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Tests --lpath prepends to package.path', function() + it('require test module', function() + local mod = require('cl_test_module') + assert.is_equal('test module', mod) + end) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 54600529..9d3fac22 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -167,6 +167,13 @@ describe('Tests the busted command-line options', function() assert.is_equal(expected, result) end) + it('tests running with --lpath specified', function() + local success, exitcode + success, exitcode = execute('bin/busted --lpath="spec/?.lua" spec/cl_lua_path.lua') + assert.is_true(success) + assert.is_equal(0, exitcode) + end) + it('tests running with --lang specified', function() local success, exitcode error_start() diff --git a/spec/cl_test_module.lua b/spec/cl_test_module.lua new file mode 100644 index 00000000..5db7dc4e --- /dev/null +++ b/spec/cl_test_module.lua @@ -0,0 +1 @@ +return 'test module' From b2f41f38e3e9c548ece0277782d9df0ff0b3e8e0 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 6 Feb 2015 00:13:53 -0800 Subject: [PATCH 097/293] Fix `.busted` task loading Any arguments specified on the command-line should override those set in the `.busted` task profile. However, the configuration loader was doing the opposite, overriding command-line arguments with values in the `.busted` task profile. Fixes issue #327 --- busted/modules/configuration_loader.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index c6dab900..59324dd5 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -14,8 +14,7 @@ return function() local runConfig = configFile[run] if type(runConfig) == 'table' then - - config = tablex.merge(config, runConfig, true) + config = tablex.merge(runConfig, config, true) return config else return config, 'Task `' .. run .. '` not found, or not a table.' @@ -23,7 +22,7 @@ return function() end if configFile and type(configFile.default) == 'table' then - config = tablex.merge(config, configFile.default, true) + config = tablex.merge(configFile.default, config, true) end return config From 7e98bade28b560000b755fca9e0e2b0bb1254694 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 31 Dec 2014 01:52:26 -0800 Subject: [PATCH 098/293] Restrict luassert variables to busted environment The luassert variables assert/spy/mock/stub should only be visible inside a busted context. Other modules outside of busted should be free to reuse these variable names without interfering with the test environment. If other modules need to use luassert, they should explicitly `require` it. Otherwise, `assert` should default to the builtin Lua `assert`. --- busted/core.lua | 17 ++++++++++------- busted/init.lua | 15 ++++++++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 6d1b99dd..9ebb8d07 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -41,6 +41,16 @@ return function() busted.context = root.ref() local environment = require 'busted.environment'(busted.context) + busted.environment = { + set = environment.set, + + wrap = function(callable) + if (type(callable) == 'function' or getmetatable(callable).__call) then + -- prioritize __call if it exists, like in files + environment.wrap((getmetatable(callable) or {}).__call or callable) + end + end + } busted.executors = {} local executors = {} @@ -139,13 +149,6 @@ return function() setfenv(f, env) end - function busted.wrapEnv(callable) - if (type(callable) == 'function' or getmetatable(callable).__call) then - -- prioritize __call if it exists, like in files - environment.wrap((getmetatable(callable) or {}).__call or callable) - end - end - function busted.safe(descriptor, run, element) busted.context.push(element) local trace, message diff --git a/busted/init.lua b/busted/init.lua index 400399a2..5f88b5e6 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -83,7 +83,7 @@ local function init(busted) local file = function(file) busted.publish({ 'file', 'start' }, file.name) - busted.wrapEnv(file.run) + busted.environment.wrap(file.run) if not file.env then file.env = {} end local randomize = busted.randomize @@ -194,10 +194,15 @@ local function init(busted) busted.alias('spec', 'it') busted.alias('test', 'it') - assert = require 'luassert' - spy = require 'luassert.spy' - mock = require 'luassert.mock' - stub = require 'luassert.stub' + local assert = require 'luassert' + local spy = require 'luassert.spy' + local mock = require 'luassert.mock' + local stub = require 'luassert.stub' + + busted.environment.set('assert', assert) + busted.environment.set('spy', spy) + busted.environment.set('mock', mock) + busted.environment.set('stub', stub) busted.replaceErrorWithFail(assert) busted.replaceErrorWithFail(assert.True) From fa528e6101579705ba13ca20504046932dbc5cd2 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 5 Jan 2015 12:33:41 -0800 Subject: [PATCH 099/293] Update luassert version to 1.7.4-0 in rockspec --- busted-2.0.rc5-0.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted-2.0.rc5-0.rockspec b/busted-2.0.rc5-0.rockspec index 7a2911d5..8790c058 100644 --- a/busted-2.0.rc5-0.rockspec +++ b/busted-2.0.rc5-0.rockspec @@ -23,7 +23,7 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.2-1', - 'luassert >= 1.7.3-0', + 'luassert >= 1.7.4-0', 'ansicolors >= 1.0-1', 'penlight >= 1.0.0-1', 'mediator_lua >= 1.1-3', From cfe5d1afb095f8c6da81979f97a3e7298834cc5e Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Tue, 10 Feb 2015 20:17:19 -0800 Subject: [PATCH 100/293] Release 2.0-rc6 --- busted-2.0.rc5-0.rockspec => busted-2.0.rc6-0.rockspec | 6 +++--- busted/core.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename busted-2.0.rc5-0.rockspec => busted-2.0.rc6-0.rockspec (96%) diff --git a/busted-2.0.rc5-0.rockspec b/busted-2.0.rc6-0.rockspec similarity index 96% rename from busted-2.0.rc5-0.rockspec rename to busted-2.0.rc6-0.rockspec index 8790c058..2e1f2d0f 100644 --- a/busted-2.0.rc5-0.rockspec +++ b/busted-2.0.rc6-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc5-0' +version = '2.0.rc6-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc5.tar.gz', - dir = 'busted-2.0.rc5' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc6.tar.gz', + dir = 'busted-2.0.rc6' } description = { summary = 'Elegant Lua unit testing.', diff --git a/busted/core.lua b/busted/core.lua index 9ebb8d07..c69a142a 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -35,7 +35,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc5-0' + busted.version = '2.0.rc6-0' local root = require 'busted.context'() busted.context = root.ref() From 3261a67344fe993352af734fa707bbb34183c360 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 13 Feb 2015 00:28:03 -0800 Subject: [PATCH 101/293] Access busted root context environment This allows helper modules to use variables/functions declared in the busted environment, such as `assert`, `spy`, `mock`, and `stub`. This complements the spec declarations methods (`describe`, `it`, etc.), which can already be used by helper modules. --- busted/init.lua | 5 +++-- spec/executors_spec.lua | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 5f88b5e6..954a529a 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -212,11 +212,12 @@ end return setmetatable({}, { __call = function(self, busted) + local root = busted.context.get() init(busted) return setmetatable(self, { - __index = function(self, descriptor) - return busted.executors[descriptor] + __index = function(self, key) + return rawget(root.env, key) or busted.executors[key] end, __newindex = function(self, key, value) diff --git a/spec/executors_spec.lua b/spec/executors_spec.lua index 7f3f420f..59b302be 100644 --- a/spec/executors_spec.lua +++ b/spec/executors_spec.lua @@ -38,6 +38,13 @@ describe('tests require "busted"', function() assert.is_equal(after_each, require 'busted'.after_each) end) + it('imports assert and mocks', function() + assert.is_equal(assert, require 'busted'.assert) + assert.is_equal(spy, require 'busted'.spy) + assert.is_equal(mock, require 'busted'.mock) + assert.is_equal(stub, require 'busted'.stub) + end) + it('functions cannot be overwritten', function() local foo = function() assert(false) end assert.has_error(function() require 'busted'.it = foo end) From 93da9ccb2579199c66b950ba3d94f35ff152c3f7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 14 Feb 2015 23:59:44 -0800 Subject: [PATCH 102/293] Default output handler depends on stdout is tty Set default output handler to `utfTerminal` if `stdout` is a tty, otherwise set the default output handler to `plainTerminal`. This allows file redirection to automatically default to `plainTerminal`. In addition, there is no need to have any special logic for Windows since the `ansicolors` module already takes care of this by removing any ansi color codes when running on Windows, only enabling ansi color codes when ansicon is present. --- busted-2.0.rc6-0.rockspec | 1 + busted/runner.lua | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/busted-2.0.rc6-0.rockspec b/busted-2.0.rc6-0.rockspec index 2e1f2d0f..a0f04bb4 100644 --- a/busted-2.0.rc6-0.rockspec +++ b/busted-2.0.rc6-0.rockspec @@ -25,6 +25,7 @@ dependencies = { 'say >= 1.2-1', 'luassert >= 1.7.4-0', 'ansicolors >= 1.0-1', + 'lua-term >= 0.1-1', 'penlight >= 1.0.0-1', 'mediator_lua >= 1.1-3', } diff --git a/busted/runner.lua b/busted/runner.lua index ac35bcaa..609a0c33 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -3,6 +3,7 @@ local getfenv = require 'busted.compatibility'.getfenv local setfenv = require 'busted.compatibility'.setfenv local path = require 'pl.path' +local term = require 'term' local utils = require 'busted.utils' local loaded = false @@ -22,7 +23,7 @@ return function(options) require 'busted'(busted) -- Default cli arg values - local defaultOutput = path.is_windows and 'plainTerminal' or 'utfTerminal' + local defaultOutput = term.isatty(io.stdout) and 'utfTerminal' or 'plainTerminal' local defaultLoaders = 'lua,moonscript' local defaultPattern = '_spec' local defaultSeed = 'os.time()' From a14c3393d974a0712919d6c8ebe97587aad4f9c3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 15 Feb 2015 22:21:16 -0800 Subject: [PATCH 103/293] Fix cl_spec to work on Windows --- spec/cl_spec.lua | 198 +++++++++++++++++++++++------------------------ 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index b4fa4674..acd12173 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -1,9 +1,9 @@ local utils = require 'pl.utils' -local path = require('pl.path') -local ditch = ' > /dev/null 2>&1' -if path.is_windows then - ditch = ' 1> NUL 2>NUL' -end +local path = require 'pl.path' +local normpath = require 'busted.utils'.normpath +local busted_cmd = path.is_windows and 'lua bin/busted' or 'bin/busted' +local ditch = path.is_windows and ' 1> NUL 2>NUL' or ' > /dev/null 2>&1' + --ditch = '' -- uncomment this line, to show output of failing commands, for debugging local error_started @@ -62,13 +62,13 @@ describe('Tests the busted command-line options', function() it('tests running with --tags specified', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_tags.lua$') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$') assert.is_false(success) assert.is_equal(8, exitcode) - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag1') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag1,tag2') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1,tag2') assert.is_false(success) assert.is_equal(4, exitcode) error_end() @@ -77,10 +77,10 @@ describe('Tests the busted command-line options', function() it('tests running with --exclude-tags specified', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') assert.is_false(success) assert.is_equal(2, exitcode) error_end() @@ -89,10 +89,10 @@ describe('Tests the busted command-line options', function() it('tests running with --tags and --exclude-tags specified', function () local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') assert.is_false(success) assert.is_equal(1, exitcode) - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') assert.is_false(success) assert.is_equal(1, exitcode) error_end() @@ -101,10 +101,10 @@ describe('Tests the busted command-line options', function() it('tests running with --tags specified in describe', function () local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=dtag1') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=dtag1') assert.is_false(success) assert.is_equal(5, exitcode) - success, exitcode = execute('bin/busted --pattern=_tags.lua$ --tags=dtag2') + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=dtag2') assert.is_false(success) assert.is_equal(1, exitcode) error_end() @@ -113,13 +113,13 @@ describe('Tests the busted command-line options', function() it('tests running with --filter specified', function () local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_filter.lua$') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$') assert.is_false(success) assert.is_equal(8, exitcode) - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern1"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern1"') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern2"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern2"') assert.is_false(success) assert.is_equal(2, exitcode) error_end() @@ -128,13 +128,13 @@ describe('Tests the busted command-line options', function() it('tests running with --filter-out specified', function () local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter-out="pattern1"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="pattern1"') assert.is_false(success) assert.is_equal(6, exitcode) - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter-out="pattern%d"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="pattern%d"') assert.is_false(success) assert.is_equal(5, exitcode) - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter-out="patt.*(%d)"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="patt.*(%d)"') assert.is_true(success) error_end() end) @@ -142,7 +142,7 @@ describe('Tests the busted command-line options', function() it('tests running with --filter and --filter-out specified', function () local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') assert.is_true(success) error_end() end) @@ -150,26 +150,26 @@ describe('Tests the busted command-line options', function() it('tests running with --filter specified in describe', function () local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="patt1"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="patt1"') assert.is_false(success) assert.is_equal(5, exitcode) - success, exitcode = execute('bin/busted --pattern=_filter.lua$ --filter="patt2"') + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="patt2"') assert.is_false(success) assert.is_equal(1, exitcode) error_end() end) it('tests running with --list specified', function() - local result = run('bin/busted --list --pattern=cl_list.lua$') + local result = run(busted_cmd .. ' --list --pattern=cl_list.lua$') local expected = './spec/cl_list.lua:4: Tests list test 1\n' .. './spec/cl_list.lua:7: Tests list test 2\n' .. './spec/cl_list.lua:10: Tests list test 3\n' - assert.is_equal(expected, result) + assert.is_equal(normpath(expected), result) end) it('tests running with --lpath specified', function() local success, exitcode - success, exitcode = execute('bin/busted --lpath="spec/?.lua" spec/cl_lua_path.lua') + success, exitcode = execute(busted_cmd .. ' --lpath="spec/?.lua" spec/cl_lua_path.lua') assert.is_true(success) assert.is_equal(0, exitcode) end) @@ -177,10 +177,10 @@ describe('Tests the busted command-line options', function() it('tests running with --lang specified', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=cl_success.lua$ --lang=en') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_success.lua$ --lang=en') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute('bin/busted --pattern=cl_success --lang=not_found_here') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_success --lang=not_found_here') assert.is_false(success) assert.is_equal(1, exitcode) -- busted errors out on non-available language error_end() @@ -188,14 +188,14 @@ describe('Tests the busted command-line options', function() it('tests running with --version specified', function() local success, exitcode - success, exitcode = execute('bin/busted --version') + success, exitcode = execute(busted_cmd .. ' --version') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests running with --help specified', function() local success, exitcode - success, exitcode = execute('bin/busted --help') + success, exitcode = execute(busted_cmd .. ' --help') assert.is_false(success) assert.is_equal(1, exitcode) end) @@ -203,7 +203,7 @@ describe('Tests the busted command-line options', function() it('tests running a non-compiling testfile', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=cl_compile_fail.lua$') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_compile_fail.lua$') assert.is_false(success) assert.is_equal(1, exitcode) error_end() @@ -212,7 +212,7 @@ describe('Tests the busted command-line options', function() it('tests running a testfile throwing errors when being run', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=cl_execute_fail.lua$') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_execute_fail.lua$') assert.is_false(success) assert.is_equal(1, exitcode) error_end() @@ -221,10 +221,10 @@ describe('Tests the busted command-line options', function() it('tests running with --output specified', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=cl_success.lua$ --output=TAP') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_success.lua$ --output=TAP') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute('bin/busted --pattern=cl_two_failures.lua$ --output=not_found_here') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_two_failures.lua$ --output=not_found_here') assert.is_false(success) assert.is_equal(3, exitcode) -- outputter missing, defaults to default outputter +1 error error_end() @@ -233,7 +233,7 @@ describe('Tests the busted command-line options', function() it('tests running with --output specified with module in lua path', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') assert.is_true(success) assert.is_equal(0, exitcode) error_end() @@ -242,7 +242,7 @@ describe('Tests the busted command-line options', function() it('tests no tests to exit with a fail-exitcode', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=this_filename_does_simply_not_exist$') + success, exitcode = execute(busted_cmd .. ' --pattern=this_filename_does_simply_not_exist$') assert.is_false(success) assert.is_equal(1, exitcode) error_end() @@ -254,7 +254,7 @@ describe('Tests failing tests through the commandline', function() it('tests failing setup/before_each/after_each/teardown functions', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=cl_failing_support.lua$') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_failing_support.lua$') assert.is_false(success) assert.is_equal(8, exitcode) error_end() @@ -262,7 +262,7 @@ describe('Tests failing tests through the commandline', function() it('tests failing support functions as errors', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_failing_support.lua$') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_failing_support.lua$') local _, numErrors = result:gsub('Error → .-\n','') assert.is_equal(12, numErrors) error_end() @@ -328,13 +328,13 @@ describe('Test busted command-line runner', function() it('runs standalone spec', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted spec/cl_standalone.lua') + success, exitcode = execute(busted_cmd .. ' spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute('bin/busted --tags=tag1 spec/cl_standalone.lua') + success, exitcode = execute(busted_cmd .. ' --tags=tag1 spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(2, exitcode) - success, exitcode = execute('bin/busted --tags=tag1,tag2 spec/cl_standalone.lua') + success, exitcode = execute(busted_cmd .. ' --tags=tag1,tag2 spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, exitcode) error_end() @@ -344,7 +344,7 @@ end) describe('Tests distinguish between errors and failures', function() it('by detecting errors as test errors', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') local errmsg = result:match('(Error → .-)\n') assert.is_truthy(errmsg) error_end() @@ -352,7 +352,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting assert failures as test failures', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_two_failures.lua$') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$') local failmsg = result:match('(Failure → .-)\n') assert.is_truthy(failmsg) error_end() @@ -360,7 +360,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting Lua runtime errors as test errors', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=luaerr') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=luaerr') local failmsg = result:match('(Error → .-)\n') assert.is_truthy(failmsg) error_end() @@ -370,34 +370,34 @@ end) describe('Tests stack trackback', function() it('when throwing an error', function() error_start() - local result = run('bin/busted --verbose --pattern=cl_errors.lua$ --tags=testerr') + local result = run(busted_cmd .. ' --verbose --pattern=cl_errors.lua$ --tags=testerr') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: ./spec/cl_errors.lua:6: in function <./spec/cl_errors.lua:5> ]] - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when assertion fails', function() error_start() - local result = run('bin/busted --verbose --pattern=cl_two_failures.lua$ --tags=err1') + local result = run(busted_cmd .. ' --verbose --pattern=cl_two_failures.lua$ --tags=err1') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: ./spec/cl_two_failures.lua:6: in function <./spec/cl_two_failures.lua:5> ]] - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when Lua runtime error', function() error_start() - local result = run('bin/busted --verbose --pattern=cl_errors.lua$ --tags=luaerr') + local result = run(busted_cmd .. ' --verbose --pattern=cl_errors.lua$ --tags=luaerr') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: ./spec/cl_errors.lua:11: in function <./spec/cl_errors.lua:9> ]] - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) end) @@ -405,76 +405,76 @@ end) describe('Tests error messages through the command line', function() it('when throwing errors in a test', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') local err = result:match('(Error → .-)\n') - local errmsg = result:match('\n(%./spec/.-)\n') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expectedErr = "Error → ./spec/cl_errors.lua @ 5" local expectedMsg = "./spec/cl_errors.lua:6: force an error" - assert.is_equal(expectedErr, err) - assert.is_equal(expectedMsg, errmsg) + assert.is_equal(normpath(expectedErr), err) + assert.is_equal(normpath(expectedMsg), errmsg) error_end() end) it('when throwing an error table', function() error_start() - local result = run('bin/busted --output=plainTerminal --tags=table --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%./spec/.-)\n') + local result = run(busted_cmd .. ' --output=plainTerminal --tags=table --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expected = './spec/cl_error_messages.lua:5: {' - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when throwing a nil error', function() error_start() - local result = run('bin/busted --output=plainTerminal --tags=nil --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%./spec/.-)\n') + local result = run(busted_cmd .. ' --output=plainTerminal --tags=nil --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expected = './spec/cl_error_messages.lua:9: Nil error' - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when throwing an error table with __tostring', function() error_start() - local result = run('bin/busted --output=plainTerminal --tags=tostring --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%./spec/.-)\n') + local result = run(busted_cmd .. ' --output=plainTerminal --tags=tostring --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expected = './spec/cl_error_messages.lua:17: {}' - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when throwing after a pcall', function() error_start() - local result = run('bin/busted --output=plainTerminal --tags=pcall --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%./spec/.-)\n') + local result = run(busted_cmd .. ' --output=plainTerminal --tags=pcall --pattern=cl_error_messages.lua$') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expected = './spec/cl_error_messages.lua:22: error after pcall' - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when running a non-compiling testfile', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_compile_fail.lua$') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_compile_fail.lua$') local errmsg = result:match('(Error → .-:%d+:) ') local expected = "Error → ./spec/cl_compile_fail.lua:3:" - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when a testfile throws errors', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_execute_fail.lua$') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_execute_fail.lua$') local err = result:match('(Error → .-)\n') - local errmsg = result:match('\n(%./spec/cl_execute_fail%.lua:%d+:.-)\n') + local errmsg = result:match('\n(%.[/\\]spec[/\\]cl_execute_fail%.lua:%d+:.-)\n') local expectedErr = 'Error → ./spec/cl_execute_fail.lua @ 4' local expectedMsg = './spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' - assert.is_equal(expectedErr, err) - assert.is_equal(expectedMsg, errmsg) + assert.is_equal(normpath(expectedErr), err) + assert.is_equal(normpath(expectedMsg), errmsg) error_end() end) it('when output library not found', function() error_start() - local result = run('bin/busted --pattern=cl_two_failures.lua$ --output=not_found_here') + local result = run(busted_cmd .. ' --pattern=cl_two_failures.lua$ --output=not_found_here') local errmsg = result:match('(.-)\n') local expected = 'Cannot load output library: not_found_here' assert.is_equal(expected, errmsg) @@ -483,7 +483,7 @@ describe('Tests error messages through the command line', function() it('when no test files matching Lua pattern', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') local errmsg = result:match('(.-)\n') local expected = 'No test files found matching Lua pattern: this_filename_does_simply_not_exist$' assert.is_equal(expected, errmsg) @@ -494,43 +494,43 @@ end) describe('Tests moonscript error messages through the command line', function() it('when assertion fails', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') local err = result:match('(Failure → .-)\n') - local errmsg = result:match('\n(%./spec/.-)\n') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expectedErr = "Failure → ./spec/cl_moonscript_error_messages.moon @ 4" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." - assert.is_equal(expectedErr, err) - assert.is_equal(expectedMsg, errmsg) + assert.is_equal(normpath(expectedErr), err) + assert.is_equal(normpath(expectedMsg), errmsg) error_end() end) it('when throwing string errors', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') local err = result:match('(Error → .-)\n') - local errmsg = result:match('\n(%./spec/.-)\n') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expectedErr = "Error → ./spec/cl_moonscript_error_messages.moon @ 16" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:17: error message" - assert.is_equal(expectedErr, err) - assert.is_equal(expectedMsg, errmsg) + assert.is_equal(normpath(expectedErr), err) + assert.is_equal(normpath(expectedMsg), errmsg) error_end() end) it('when throwing an error table', function() error_start() - local result = run('bin/busted --output=plainTerminal --tags=table --pattern=cl_moonscript_error_messages.moon$') - local errmsg = result:match('\n(%./spec/.-)\n') + local result = run(busted_cmd .. ' --output=plainTerminal --tags=table --pattern=cl_moonscript_error_messages.moon$') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expected = './spec/cl_moonscript_error_messages.moon:9: {' - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) it('when throwing a nil error', function() error_start() - local result = run('bin/busted --output=plainTerminal --tags=nil --pattern=cl_moonscript_error_messages.moon$') - local errmsg = result:match('\n(%./spec/.-)\n') + local result = run(busted_cmd .. ' --output=plainTerminal --tags=nil --pattern=cl_moonscript_error_messages.moon$') + local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') local expected = './spec/cl_moonscript_error_messages.moon:13: Nil error' - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) error_end() end) end) @@ -539,7 +539,7 @@ describe('Tests pending through the commandline', function() it('skips tests inside pending scope', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --pattern=cl_pending.lua$') + success, exitcode = execute(busted_cmd .. ' --pattern=cl_pending.lua$') assert.is_true(success) assert.is_equal(0, exitcode) error_end() @@ -547,7 +547,7 @@ describe('Tests pending through the commandline', function() it('detects tests as pending', function() error_start() - local result = run('bin/busted --output=plainTerminal --pattern=cl_pending.lua$') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') local _, numPending = result:gsub('Pending → .-\n', '') @@ -558,7 +558,7 @@ describe('Tests pending through the commandline', function() it('--suppress-pending option is honored', function() error_start() - local result = run('bin/busted --output=plainTerminal --suppress-pending --pattern=cl_pending.lua$') + local result = run(busted_cmd .. ' --output=plainTerminal --suppress-pending --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') local _, numPending = result:gsub('Pending → .-\n', '') @@ -572,7 +572,7 @@ describe('Tests random seed through the commandline', function() it('test seed value', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --seed=12345 --pattern=cl_random_seed.lua$') + success, exitcode = execute(busted_cmd .. ' --seed=12345 --pattern=cl_random_seed.lua$') assert.is_true(success) assert.is_equal(0, exitcode) error_end() @@ -581,7 +581,7 @@ describe('Tests random seed through the commandline', function() it('test invalid seed value defaults to a valid seed value', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --seed=abcd --pattern=cl_random_seed.lua$') + success, exitcode = execute(busted_cmd .. ' --seed=abcd --pattern=cl_random_seed.lua$') assert.is_false(success) assert.is_equal(2, exitcode) -- fails cl_random_seed test +1 error error_end() @@ -589,7 +589,7 @@ describe('Tests random seed through the commandline', function() it('test failure outputs random seed value', function() error_start() - local result = run('bin/busted --seed=789 --pattern=cl_random_seed.lua$') + local result = run(busted_cmd .. ' --seed=789 --pattern=cl_random_seed.lua$') local seed = result:match('Random Seed: (%d+)\n') assert.is_equal(789, tonumber(seed)) error_end() @@ -597,7 +597,7 @@ describe('Tests random seed through the commandline', function() it('test non-randomized failure does not output seed value', function() error_start() - local result = run('bin/busted --seed=789 --pattern=cl_two_failures.lua$') + local result = run(busted_cmd .. ' --seed=789 --pattern=cl_two_failures.lua$') local seed = result:match('Random Seed:') assert.is_equal(nil, seed) error_end() @@ -609,7 +609,7 @@ describe('Tests shuffle commandline option', function() it('forces test shuffling for non-randomized tests, ' .. opt, function() local success, exitcode error_start() - success, exitcode = execute('bin/busted ' .. opt .. ' --pattern=cl_randomize.lua$') + success, exitcode = execute(busted_cmd .. ' ' .. opt .. ' --pattern=cl_randomize.lua$') assert.is_true(success) assert.is_equal(0, exitcode) error_end() @@ -622,7 +622,7 @@ describe('Tests sort commandline option', function() it('sorts tests by name, ' .. opt, function() local success, exitcode error_start() - success, exitcode = execute('bin/busted ' .. opt .. ' --pattern=cl_sort.lua$') + success, exitcode = execute(busted_cmd .. ' ' .. opt .. ' --pattern=cl_sort.lua$') assert.is_true(success) assert.is_equal(0, exitcode) error_end() @@ -634,7 +634,7 @@ describe('Tests repeat commandline option', function() it('forces tests to repeat n times', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --repeat=2 --pattern=cl_two_failures.lua$') + success, exitcode = execute(busted_cmd .. ' --repeat=2 --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(4, exitcode) error_end() @@ -645,7 +645,7 @@ describe('Tests no-keep-going commandline option', function() it('skips all tests after first error', function() local success, exitcode error_start() - success, exitcode = execute('bin/busted --no-keep-going --pattern=cl_two_failures.lua$') + success, exitcode = execute(busted_cmd .. ' --no-keep-going --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(1, exitcode) error_end() From bf79a0ddfe23a2f7c9d7270fbd7441ca8d3c1310 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 15 Feb 2015 22:56:34 -0800 Subject: [PATCH 104/293] Add command-line flag --no-recurse This allows busted to run tests in a directory without recursing into any subdirectories. --- busted/modules/test_file_loader.lua | 3 ++- busted/runner.lua | 2 ++ completions/bash/busted.bash | 1 + completions/zsh/_busted | 1 + spec/cl_spec.lua | 11 +++++++++++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 0a4ae89c..63102010 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -17,7 +17,8 @@ return function(busted, loaders, options) fileList = { rootFile } elseif path.isdir(rootFile) then local pattern = pattern - fileList = dir.getallfiles(rootFile) + local getfiles = options.recurse and dir.getallfiles or dir.getfiles + fileList = getfiles(rootFile) fileList = tablex.filter(fileList, function(filename) return path.basename(filename):find(pattern) diff --git a/busted/runner.lua b/busted/runner.lua index 609a0c33..9337863e 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -64,6 +64,7 @@ return function(options) cli:add_flag('-v, --verbose', 'verbose output of errors') cli:add_flag('-s, --enable-sound', 'executes `say` command if available') cli:add_flag('--no-keep-going', 'quit after first error or failure') + cli:add_flag('--no-recurse', 'do not recurse into subdirectories') cli:add_flag('--list', 'list the names of all tests instead of running them') cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)') cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files') @@ -300,6 +301,7 @@ return function(options) verbose = cliArgs.verbose, sort = cliArgs['sort-files'] or cliArgs.sort, shuffle = cliArgs['shuffle-files'] or cliArgs.shuffle, + recurse = not cliArgs['no-recurse'], seed = busted.randomseed } diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 0173584f..89b8d9ba 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -132,6 +132,7 @@ _busted() { -c --coverage -s --enable-sound --no-keep-going + --no-recurse --shuffle --shuffle-tests --shuffle-files --sort --sort-tests --sort-files --supress-pending diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 4c572851..d02def9b 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -20,6 +20,7 @@ _busted_args=( "--version[Prints the program version and exits]" "--list[List the names of all tests instead of running them]" "--no-keep-going[Quit after first error or failure]" +"--no-recurse[Do not recurse into subdirectories]" "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" "(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index acd12173..01ddac64 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -651,3 +651,14 @@ describe('Tests no-keep-going commandline option', function() error_end() end) end) + +describe('Tests no-recurse commandline option', function() + it('does not run any tests in subdirectories', function() + local success, exitcode + error_start() + success, exitcode = execute(busted_cmd .. ' --no-recurse --pattern=cl_two_failures.lua$ .') + assert.is_false(success) + assert.is_equal(1, exitcode) + error_end() + end) +end) From b3993e681e6aa91df3ed9a20ecb572532ac4c2c3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 13 Feb 2015 00:06:28 -0800 Subject: [PATCH 105/293] Close Lua state on exit Calls `os.exit` with `close=true` to allow Lua to close the Lua state before exiting. --- busted/runner.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 9337863e..3e26b820 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -78,13 +78,13 @@ return function(options) -- Parse the cli arguments local cliArgs, hasError = cli:parse() if hasError then - os.exit(1) + os.exit(1, true) end -- Return early if only asked for the version if cliArgs.version then print(busted.version) - os.exit(0) + os.exit(0, true) end -- Load current working directory @@ -154,7 +154,7 @@ return function(options) for _, included in pairs(tags) do if excluded == included then print('Cannot use --tags and --exclude-tags for the same tags') - os.exit(1) + os.exit(1, true) end end end @@ -368,5 +368,5 @@ return function(options) exit = 255 end end - os.exit(exit) + os.exit(exit, true) end From 7043b7e4ead0dfe94461e1159435ae6527802dd6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 16 Feb 2015 13:37:22 -0800 Subject: [PATCH 106/293] Update status 'dot' characters for utf terminal Use different characters for success, failure, error, and pending status dots: * Success - filled circle * Failure - filled square * Error - heavy asterisk * Pending - dotted circle --- busted/outputHandlers/utfTerminal.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 44451aa0..b66e0329 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -5,10 +5,10 @@ local pretty = require 'pl.pretty' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) - local successDot = ansicolors('%{green}●') - local failureDot = ansicolors('%{red}●') - local errorDot = ansicolors('%{magenta}●') - local pendingDot = ansicolors('%{yellow}●') + local successDot = ansicolors('%{green}●') + local failureDot = ansicolors('%{red}◼') + local errorDot = ansicolors('%{magenta}✱') + local pendingDot = ansicolors('%{yellow}◌') local pendingDescription = function(pending) local name = pending.name From d3ff54291d904e75cad558c8853f5c87dd1bffee Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 17 Feb 2015 15:02:32 -0800 Subject: [PATCH 107/293] Fix junit output This fixes the following errors in the junit output handler: * Skip test count * Failure stack trace message * Missing error tags for describe/it errors * Missing trace info causes busted to crash * Missing pending (skip) tags Fixes issue #333 --- busted/outputHandlers/junit.lua | 40 ++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 9c78c54a..051c8660 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -42,29 +42,59 @@ return function(options, busted) xml_doc:add_direct_child(testcase_node) if status == 'failure' then + local formatted = handler.inProgress[tostring(element)] xml_doc.attr.failures = xml_doc.attr.failures + 1 testcase_node:addtag('failure') - testcase_node:text(element.trace.traceback) + if next(formatted) then + testcase_node:text(formatted.message) + if formatted.trace and formatted.trace.traceback then + testcase_node:text(formatted.trace.traceback) + end + end + testcase_node:up() + elseif status == 'pending' then + local formatted = handler.inProgress[tostring(element)] + xml_doc.attr.skip = xml_doc.attr.skip + 1 + testcase_node:addtag('pending') + if next(formatted) then + testcase_node:text(formatted.message) + if formatted.trace and formatted.trace.traceback then + testcase_node:text(formatted.trace.traceback) + end + else + testcase_node:text(element.trace.traceback) + end testcase_node:up() end return nil, true end - handler.errorFile = function(element, parent, message, trace) + handler.error = function(element, parent, message, trace) xml_doc.attr.errors = xml_doc.attr.errors + 1 xml_doc:addtag('error') - xml_doc:text(trace.traceback) + xml_doc:text(message) + if trace and trace.traceback then + xml_doc:text(trace.traceback) + end xml_doc:up() return nil, true end + handler.failure = function(element, parent, message, trace) + if element.descriptor ~= 'it' then + handler.error(element, parent, message, trace) + end + + return nil, true + end + busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) - busted.subscribe({ 'error', 'file' }, handler.errorFile) - busted.subscribe({ 'failure', 'file' }, handler.errorFile) + busted.subscribe({ 'error' }, handler.error) + busted.subscribe({ 'failure' }, handler.failure) return handler end From f2f56623554f81d46c5a657f6c1111212c91d318 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 18 Feb 2015 00:39:07 -0800 Subject: [PATCH 108/293] Fix double counting of errors This fixes the case where errors are double counted when there is an error in a support function (`setup`, `teardown`, `before_each`, `after_each`) --- busted/init.lua | 2 +- busted/outputHandlers/base.lua | 46 ++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 954a529a..70340c99 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -155,7 +155,7 @@ local function init(busted) local pass, ancestor = execAll('before_each', parent, true) if pass then - status:update(busted.safe('element', element.run, element)) + status:update(busted.safe('it', element.run, element)) else updateErrorStatus('before_each') end diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index c6d24ef3..c64d1488 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -29,6 +29,8 @@ return function(busted) busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'pending' }, handler.basePending, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'failure', 'it' }, handler.baseTestFailure) + busted.subscribe({ 'error', 'it' }, handler.baseTestError) busted.subscribe({ 'failure' }, handler.baseError) busted.subscribe({ 'error' }, handler.baseError) end @@ -98,7 +100,6 @@ return function(busted) end handler.baseTestEnd = function(element, parent, status, debug) - local isError local insertTable @@ -110,10 +111,10 @@ return function(busted) handler.pendingsCount = handler.pendingsCount + 1 elseif status == 'failure' then insertTable = handler.failures - handler.failuresCount = handler.failuresCount + 1 + -- failure count already incremented in error handler elseif status == 'error' then + -- error count already incremented in error handler insertTable = handler.errors - handler.errorsCount = handler.errorsCount + 1 isError = true end @@ -133,25 +134,38 @@ return function(busted) return nil, true end - handler.basePending = function(element, parent, message, debug) - if element.descriptor == 'it' then - local id = tostring(element) - handler.inProgress[id].message = message - handler.inProgress[id].trace = debug + function saveInProgress(element, message, debug) + local id = tostring(element) + handler.inProgress[id].message = message + handler.inProgress[id].trace = debug + end + + function saveError(element, parent, message, debug) + if parent.randomseed then + message = 'Random Seed: ' .. parent.randomseed .. '\n' .. message end + saveInProgress(element, message, debug) + end + handler.basePending = function(element, parent, message, debug) + saveInProgress(element, message, debug) + return nil, true + end + + handler.baseTestFailure = function(element, parent, message, debug) + handler.failuresCount = handler.failuresCount + 1 + saveError(element, parent, message, debug) + return nil, true + end + + handler.baseTestError = function(element, parent, message, debug) + handler.errorsCount = handler.errorsCount + 1 + saveError(element, parent, message, debug) return nil, true end handler.baseError = function(element, parent, message, debug) - if element.descriptor == 'it' then - if parent.randomseed then - message = 'Random Seed: ' .. parent.randomseed .. '\n' .. message - end - local id = tostring(element) - handler.inProgress[id].message = message - handler.inProgress[id].trace = debug - else + if element.descriptor ~= 'it' then handler.errorsCount = handler.errorsCount + 1 table.insert(handler.errors, handler.format(element, parent, message, debug, true)) end From 69750b4ad1259bc77a711d277c9a8e8a3541efb3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 18 Feb 2015 15:57:38 -0800 Subject: [PATCH 109/293] Cleanup output handler loader and file loaders --- busted/modules/files/moonscript.lua | 15 ++------------- busted/modules/files/terra.lua | 14 ++------------ busted/modules/output_handler_loader.lua | 8 ++++---- 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/busted/modules/files/moonscript.lua b/busted/modules/files/moonscript.lua index 5973c929..e6eec084 100644 --- a/busted/modules/files/moonscript.lua +++ b/busted/modules/files/moonscript.lua @@ -100,21 +100,10 @@ end ret.load = function(busted, filename) - local file - - local success, err = pcall(function() - local err - file, err = moonscript.loadfile(filename) - - if not file then - busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) - end - end) - - if not success then + local file, err = moonscript.loadfile(filename) + if not file then busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) end - return file, getTrace, rewriteMessage end diff --git a/busted/modules/files/terra.lua b/busted/modules/files/terra.lua index ea485235..b1e6975d 100644 --- a/busted/modules/files/terra.lua +++ b/busted/modules/files/terra.lua @@ -18,20 +18,10 @@ ret.match = function(busted, filename) end ret.load = function(busted, filename) - local file - - local success, err = pcall(function() - file, err = terralib.loadfile(filename) - - if not file then - busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) - end - end) - - if not success then + local file, err = terralib.loadfile(filename) + if not file then busted.publish({ 'error', 'file' }, { descriptor = 'file', name = filename }, nil, err, {}) end - return file, getTrace end diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index 44808be3..7f86e839 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -1,18 +1,18 @@ -local path = require 'pl.path' +local utils = require 'busted.utils' return function() local loadOutputHandler = function(output, opath, options, busted, defaultOutput) local handler local success, err = pcall(function() - if output:match('.lua$') or output:match('.moon$') then - handler = loadfile(path.normpath(opath))() + if output:match('%.lua$') or output:match('%.moon$') then + handler = dofile(utils.normpath(opath)) else handler = require('busted.outputHandlers.' .. output) end end) - if not success then + if not success and err:match("module '.-' not found:") then success, err = pcall(function() handler = require(output) end) end From db375d2ce4dd43cf39b8cc32c1dc012444646587 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 19 Feb 2015 01:38:54 -0800 Subject: [PATCH 110/293] Refactor call to output handler loader --- busted/runner.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/busted/runner.lua b/busted/runner.lua index 3e26b820..6cae526b 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -200,7 +200,8 @@ return function(options) deferPrint = cliArgs['defer-print'] } - local outputHandler = outputHandlerLoader(cliArgs.output, cliArgs.o, outputHandlerOptions, busted, defaultOutput) + local opath = utils.normpath(path.join(fpath, cliArgs.o)) + local outputHandler = outputHandlerLoader(cliArgs.o, opath, outputHandlerOptions, busted, defaultOutput) outputHandler:subscribe(outputHandlerOptions) if cliArgs.s then From 6e09c7696fae1e1c1a2659aa3850d76081352fe7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 19 Feb 2015 00:56:00 -0800 Subject: [PATCH 111/293] Add support for loading moonscript output handlers --- busted/modules/output_handler_loader.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index 7f86e839..d5221184 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -1,12 +1,15 @@ local utils = require 'busted.utils' +local hasMoon, moonscript = pcall(require, 'moonscript') return function() local loadOutputHandler = function(output, opath, options, busted, defaultOutput) local handler local success, err = pcall(function() - if output:match('%.lua$') or output:match('%.moon$') then + if output:match('%.lua$') then handler = dofile(utils.normpath(opath)) + elseif hasMoon and output:match('%.moon$') then + handler = moonscript.dofile(utils.normpath(opath)) else handler = require('busted.outputHandlers.' .. output) end From 9f9c5c62b0deda61ba0bdc547baa3524b036b8f8 Mon Sep 17 00:00:00 2001 From: mpeterv Date: Thu, 19 Feb 2015 19:24:48 +0300 Subject: [PATCH 112/293] Removed some unused variables --- busted/core.lua | 2 +- busted/modules/configuration_loader.lua | 1 - busted/modules/test_file_loader.lua | 1 - busted/outputHandlers/json.lua | 1 - busted/outputHandlers/junit.lua | 2 +- busted/outputHandlers/sound.lua | 2 -- busted/runner.lua | 2 -- 7 files changed, 2 insertions(+), 9 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index c69a142a..802e60c8 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -100,7 +100,7 @@ return function() end function busted.getFile(element) - local current, parent = element, busted.context.parent(element) + local parent = busted.context.parent(element) while parent do if parent.file then diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index 59324dd5..83b5cef6 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -1,5 +1,4 @@ return function() - local path = require 'pl.path' local tablex = require 'pl.tablex' -- Function to load the .busted configuration file if available diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 63102010..87eee455 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -16,7 +16,6 @@ return function(busted, loaders, options) if path.isfile(rootFile) then fileList = { rootFile } elseif path.isdir(rootFile) then - local pattern = pattern local getfiles = options.recurse and dir.getallfiles or dir.getfiles fileList = getfiles(rootFile) diff --git a/busted/outputHandlers/json.lua b/busted/outputHandlers/json.lua index 185d3c30..c2d7d961 100644 --- a/busted/outputHandlers/json.lua +++ b/busted/outputHandlers/json.lua @@ -1,4 +1,3 @@ -local pretty = require 'pl.pretty' local json = require 'dkjson' return function(options, busted) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 051c8660..accc4ed1 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -5,7 +5,7 @@ local string = require("string") return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) local xml_doc - local suiteStartTime, suiteEndTime + local suiteStartTime handler.suiteStart = function() suiteStartTime = socket.gettime() diff --git a/busted/outputHandlers/sound.lua b/busted/outputHandlers/sound.lua index 705ae7d1..973e7486 100644 --- a/busted/outputHandlers/sound.lua +++ b/busted/outputHandlers/sound.lua @@ -1,5 +1,3 @@ -local pretty = require 'pl.pretty' - return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) local language = require('busted.languages.' .. options.language) diff --git a/busted/runner.lua b/busted/runner.lua index 6cae526b..dea2ee1b 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -1,7 +1,5 @@ -- Busted command-line runner -local getfenv = require 'busted.compatibility'.getfenv -local setfenv = require 'busted.compatibility'.setfenv local path = require 'pl.path' local term = require 'term' local utils = require 'busted.utils' From dcfaeb9fff6413cb8a42048bf7f7f563bbabce26 Mon Sep 17 00:00:00 2001 From: mpeterv Date: Thu, 19 Feb 2015 19:34:54 +0300 Subject: [PATCH 113/293] Simplified filename matching using penlight --- busted/modules/files/lua.lua | 8 +++----- busted/modules/files/moonscript.lua | 8 +++----- busted/modules/files/terra.lua | 10 +++------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/busted/modules/files/lua.lua b/busted/modules/files/lua.lua index 99846b11..a4218f6d 100644 --- a/busted/modules/files/lua.lua +++ b/busted/modules/files/lua.lua @@ -1,3 +1,5 @@ +local path = require 'pl.path' + local ret = {} local getTrace = function(filename, info) @@ -7,11 +9,7 @@ local getTrace = function(filename, info) end ret.match = function(busted, filename) - local path, name, ext = filename:match('(.-)([^\\/\\\\]-%.?([^%.\\/]*))$') - if ext == 'lua' then - return true - end - return false + return path.extension(filename) == '.lua' end diff --git a/busted/modules/files/moonscript.lua b/busted/modules/files/moonscript.lua index e6eec084..145b942f 100644 --- a/busted/modules/files/moonscript.lua +++ b/busted/modules/files/moonscript.lua @@ -1,3 +1,5 @@ +local path = require 'pl.path' + local ok, moonscript, line_tables, util = pcall(function() return require 'moonscript', require 'moonscript.line_tables', require 'moonscript.util' end) @@ -91,11 +93,7 @@ local rewriteMessage = function(filename, message) end ret.match = function(busted, filename) - local path, name, ext = filename:match('(.-)([^\\/\\\\]-%.?([^%.\\/]*))$') - if ok and ext == 'moon' then - return true - end - return false + return ok and path.extension(filename) == '.moon' end diff --git a/busted/modules/files/terra.lua b/busted/modules/files/terra.lua index b1e6975d..02956f76 100644 --- a/busted/modules/files/terra.lua +++ b/busted/modules/files/terra.lua @@ -1,3 +1,5 @@ +local path = require 'pl.path' + local ret = {} local ok, terralib = pcall(function() return require 'terralib' end) @@ -8,13 +10,7 @@ local getTrace = function(filename, info) end ret.match = function(busted, filename) - if ok then - local path, name, ext = filename:match('(.-)([^\\/\\\\]-%.?([^%.\\/]*))$') - if ext == 't' then - return true - end - end - return false + return ok and path.extension(filename) == '.t' end ret.load = function(busted, filename) From 5f1e601b4e18ab9b8f688cbd5d93764816d2123a Mon Sep 17 00:00:00 2001 From: mpeterv Date: Thu, 19 Feb 2015 19:46:46 +0300 Subject: [PATCH 114/293] Fixed accidental global variables --- busted/init.lua | 2 +- busted/outputHandlers/TAP.lua | 2 +- busted/outputHandlers/base.lua | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 70340c99..4e81944c 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -172,7 +172,7 @@ local function init(busted) end local pending = function(element) - local parent = busted.context.parent(pending) + local parent = busted.context.parent(element) busted.publish({ 'test', 'start' }, element, parent) busted.publish({ 'test', 'end' }, element, parent, 'pending') end diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index d6efb4fe..3eeadb99 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -16,7 +16,7 @@ return function(options, busted) print( success:format( counter, t.name )) end - showFailure = function(t) + local showFailure = function(t) counter = counter + 1 local message = t.message diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index c64d1488..5dc60ef2 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -134,13 +134,13 @@ return function(busted) return nil, true end - function saveInProgress(element, message, debug) + local function saveInProgress(element, message, debug) local id = tostring(element) handler.inProgress[id].message = message handler.inProgress[id].trace = debug end - function saveError(element, parent, message, debug) + local function saveError(element, parent, message, debug) if parent.randomseed then message = 'Random Seed: ' .. parent.randomseed .. '\n' .. message end From 20e4b86fab25d203c1d97045df8cabd656061c3f Mon Sep 17 00:00:00 2001 From: John Szakmeister Date: Fri, 20 Feb 2015 06:13:02 -0500 Subject: [PATCH 115/293] Add a timestamp to the testsuite tag in the jUnit test report. --- busted/outputHandlers/junit.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 051c8660..f3706666 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -14,6 +14,7 @@ return function(options, busted) errors = 0, failures = 0, skip = 0, + timestamp = os.date('!%Y-%m-%dT%T'), }) return nil, true From 658ba174120627d58f4919816fd2d617196c80d8 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 20 Feb 2015 11:29:41 -0800 Subject: [PATCH 116/293] Add stack trace to TAP failure message Enable stack trace info in TAP failures with the verbose option. --- busted/outputHandlers/TAP.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index d6efb4fe..c284bfbd 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -13,12 +13,13 @@ return function(options, busted) for i,t in pairs(handler.successes) do counter = counter + 1 - print( success:format( counter, t.name )) + print(success:format(counter, t.name)) end showFailure = function(t) counter = counter + 1 local message = t.message + local trace = t.trace or {} if message == nil then message = 'Nil error' @@ -26,9 +27,12 @@ return function(options, busted) message = pretty.write(message) end - print( failure:format( counter, t.name )) + print(failure:format(counter, t.name)) print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) - print('# Failure message: ' .. message:gsub('\n', '\n# ' )) + print('# Failure message: ' .. message:gsub('\n', '\n# ')) + if options.verbose and trace.traceback then + print('# ' .. trace.traceback:gsub('^\n', '', 1):gsub('\n', '\n# ')) + end end for i,t in pairs(handler.errors) do From 476df1ad21b13f6ba29051d69e7430cb554650ed Mon Sep 17 00:00:00 2001 From: Zhen Wang Date: Sun, 22 Feb 2015 12:58:03 +0800 Subject: [PATCH 117/293] Variable 'parent' is accessed before it is defined --- busted/init.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 70340c99..2cdcb848 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -133,6 +133,7 @@ local function init(busted) local it = function(element) local finally + local parent = busted.context.parent(element) busted.publish({ 'test', 'start' }, element, parent) @@ -151,9 +152,7 @@ local function init(busted) status:update('error') end - local parent = busted.context.parent(element) local pass, ancestor = execAll('before_each', parent, true) - if pass then status:update(busted.safe('it', element.run, element)) else From d0d7690cd99eabe1d799dad7d880d6c6f4226d0d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 8 Feb 2015 00:10:04 -0800 Subject: [PATCH 118/293] Forward command-line options to output handler Add command-line option to forward options to the output handler. Use the `-Xoutput` option to pass options to the output handler. If the argument to `-Xoutput` contains commas, then it is split into multiple options at the commas. --- busted-2.0.rc6-0.rockspec | 2 +- busted/runner.lua | 9 ++++++--- spec/cl_output_handler.lua | 25 +++++++++++++++++++++++++ spec/cl_spec.lua | 20 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 spec/cl_output_handler.lua diff --git a/busted-2.0.rc6-0.rockspec b/busted-2.0.rc6-0.rockspec index a0f04bb4..d11054fa 100644 --- a/busted-2.0.rc6-0.rockspec +++ b/busted-2.0.rc6-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.0', + 'lua_cliargs >= 2.3-0', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.2-1', diff --git a/busted/runner.lua b/busted/runner.lua index 6cae526b..582e2636 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -60,6 +60,8 @@ return function(options) cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) cli:add_option('--helper=PATH', 'A helper script that is run before tests') + cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.') + cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') cli:add_flag('-v, --verbose', 'verbose output of errors') cli:add_flag('-s, --enable-sound', 'executes `say` command if available') @@ -76,8 +78,8 @@ return function(options) cli:add_flag('--defer-print', 'defer print to when test suite is complete') -- Parse the cli arguments - local cliArgs, hasError = cli:parse() - if hasError then + local cliArgs = cli:parse(arg) + if not cliArgs then os.exit(1, true) end @@ -197,7 +199,8 @@ return function(options) verbose = cliArgs.verbose, suppressPending = cliArgs['suppress-pending'], language = cliArgs.lang, - deferPrint = cliArgs['defer-print'] + deferPrint = cliArgs['defer-print'], + arguments = utils.split(cliArgs.Xoutput, ',') or {} } local opath = utils.normpath(path.join(fpath, cliArgs.o)) diff --git a/spec/cl_output_handler.lua b/spec/cl_output_handler.lua new file mode 100644 index 00000000..2c213813 --- /dev/null +++ b/spec/cl_output_handler.lua @@ -0,0 +1,25 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +return function(options, busted) + local handler = require 'busted.outputHandlers.base'(busted) + local cli = require 'cliargs' + local args = options.arguments + + cli:set_name('cl_output_handler') + cli:add_flag('--time', 'show timestamps') + cli:add_option('--time-format=FORMAT', 'format string according to strftime', '!%c') + + local cliArgs = cli:parse(args) + + handler.testEnd = function(element, parent, status, debug) + local showTime = cliArgs.time + local timeFormat = cliArgs['time-format'] + local timestamp = showTime and ('[' .. os.date(timeFormat, 123456) .. '] ') or '' + + print(string.format("%s[%8s] %s", timestamp, status, handler.getFullName(element))) + end + + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + + return handler +end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 01ddac64..51d11ae7 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -662,3 +662,23 @@ describe('Tests no-recurse commandline option', function() error_end() end) end) + +describe('Tests Xoutput commandline option', function() + it('forwards no options to output handler when no options specified', function() + local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua --pattern=cl_success.lua$') + local status = result:match('^%[(.-)]') + assert.is_equal(' success', status) + end) + + it('forwards single option to output handler', function() + local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua -Xoutput "--time" --pattern=cl_success.lua$') + local timestamp = result:match('^%[(.-)]') + assert.is_equal('Fri Jan 2 10:17:36 1970', timestamp) + end) + + it('forwards multiple options to output handler', function() + local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua -Xoutput "--time,--time-format=!%H:%M:%S" --pattern=cl_success.lua$') + local timestamp = result:match('^%[(.-)]') + assert.is_equal('10:17:36', timestamp) + end) +end) From cc0b590a7161f64baa678b5629ac0388790a9774 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 15 Feb 2015 23:44:30 -0800 Subject: [PATCH 119/293] Add auto-completion functions for -Xoutput --- completions/bash/busted.bash | 5 +++++ completions/zsh/_busted | 1 + 2 files changed, 6 insertions(+) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 89b8d9ba..be35962b 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -101,6 +101,10 @@ _busted() { _filedir -d return 0 ;; + -Xoutput) + # no completion available + return 0 + ;; --repeat) # no completion available return 0 @@ -131,6 +135,7 @@ _busted() { --helper= -c --coverage -s --enable-sound + -Xoutput --no-keep-going --no-recurse --shuffle --shuffle-tests --shuffle-files diff --git a/completions/zsh/_busted b/completions/zsh/_busted index d02def9b..d63a4d91 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -23,6 +23,7 @@ _busted_args=( "--no-recurse[Do not recurse into subdirectories]" "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" +"-Xoutput[Pass 'OPTION' as an option to the output handler. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" "(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" "(-d --cwd)"{-d,--cwd=}"[Path to current working directory (default: ./)]:directory:_dirs" "(-h --help)"{-h,--help}"[Help]" From e7fab126826c6ffdbbcac8680cc0df9bf038a6c5 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 21 Feb 2015 00:58:29 -0800 Subject: [PATCH 120/293] Fix function signature in json output handler --- busted/outputHandlers/json.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/busted/outputHandlers/json.lua b/busted/outputHandlers/json.lua index c2d7d961..f19a336a 100644 --- a/busted/outputHandlers/json.lua +++ b/busted/outputHandlers/json.lua @@ -2,7 +2,8 @@ local json = require 'dkjson' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) - handler.suiteEnd = function(element, parent, status) + + handler.suiteEnd = function() print(json.encode({ pendings = handler.pendings, successes = handler.successes, From a5899c9656bd3e488d3ff75595f70b55f7b4278b Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 20 Feb 2015 17:29:41 -0800 Subject: [PATCH 121/293] Fix junit output to better match junit xml format Update the junit output handler to better match the junit xml format * Mark pending tests as `` * Nest errors that occur in a test inside `` --- busted/outputHandlers/junit.lua | 69 ++++++++++++++++----------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index accc4ed1..730df2c4 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -31,9 +31,7 @@ return function(options, busted) return nil, true end - handler.testEnd = function(element, parent, status) - xml_doc.attr.tests = xml_doc.attr.tests + 1 - + local function testStatus(element, parent, message, status, trace) local testcase_node = xml.new('testcase', { classname = element.trace.short_src .. ':' .. element.trace.currentline, name = handler.getFullName(element), @@ -41,50 +39,49 @@ return function(options, busted) }) xml_doc:add_direct_child(testcase_node) - if status == 'failure' then - local formatted = handler.inProgress[tostring(element)] - xml_doc.attr.failures = xml_doc.attr.failures + 1 - testcase_node:addtag('failure') - if next(formatted) then - testcase_node:text(formatted.message) - if formatted.trace and formatted.trace.traceback then - testcase_node:text(formatted.trace.traceback) - end - end + if status ~= 'success' then + testcase_node:addtag(status) + if message then testcase_node:text(message) end + if trace and trace.traceback then testcase_node:text(trace.traceback) end testcase_node:up() + end + end + + handler.testEnd = function(element, parent, status) + xml_doc.attr.tests = xml_doc.attr.tests + 1 + + if status == 'success' then + testStatus(element, parent, nil, 'success') elseif status == 'pending' then - local formatted = handler.inProgress[tostring(element)] xml_doc.attr.skip = xml_doc.attr.skip + 1 - testcase_node:addtag('pending') - if next(formatted) then - testcase_node:text(formatted.message) - if formatted.trace and formatted.trace.traceback then - testcase_node:text(formatted.trace.traceback) - end - else - testcase_node:text(element.trace.traceback) - end - testcase_node:up() + local formatted = handler.inProgress[tostring(element)] or {} + testStatus(element, parent, formatted.message, 'skipped', formatted.trace) end return nil, true end - handler.error = function(element, parent, message, trace) - xml_doc.attr.errors = xml_doc.attr.errors + 1 - xml_doc:addtag('error') - xml_doc:text(message) - if trace and trace.traceback then - xml_doc:text(trace.traceback) - end - xml_doc:up() + handler.failureTest = function(element, parent, message, trace) + xml_doc.attr.failures = xml_doc.attr.failures + 1 + testStatus(element, parent, message, 'failure', trace) + return nil, true + end + handler.errorTest = function(element, parent, message, trace) + xml_doc.attr.errors = xml_doc.attr.errors + 1 + testStatus(element, parent, message, 'error', trace) return nil, true end - handler.failure = function(element, parent, message, trace) + handler.error = function(element, parent, message, trace) if element.descriptor ~= 'it' then - handler.error(element, parent, message, trace) + xml_doc.attr.errors = xml_doc.attr.errors + 1 + xml_doc:addtag('error') + xml_doc:text(message) + if trace and trace.traceback then + xml_doc:text(trace.traceback) + end + xml_doc:up() end return nil, true @@ -93,8 +90,10 @@ return function(options, busted) busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'error', 'it' }, handler.errorTest) + busted.subscribe({ 'failure', 'it' }, handler.failureTest) busted.subscribe({ 'error' }, handler.error) - busted.subscribe({ 'failure' }, handler.failure) + busted.subscribe({ 'failure' }, handler.error) return handler end From b7cf6431529e0f7cb5b77faa13b10ce9eec74e1e Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 21 Feb 2015 00:58:06 -0800 Subject: [PATCH 122/293] Fix output handlers for multiple runs --- busted/outputHandlers/base.lua | 2 +- busted/outputHandlers/junit.lua | 78 ++++++++++++++++++------- busted/outputHandlers/plainTerminal.lua | 7 +++ busted/outputHandlers/utfTerminal.lua | 9 ++- busted/runner.lua | 13 ++--- 5 files changed, 78 insertions(+), 31 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 5dc60ef2..c380d9e0 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -23,7 +23,7 @@ return function(busted) require('busted.languages.' .. options.language) end - busted.subscribe({ 'suite', 'repeat' }, handler.baseSuiteRepeat, { priority = 1 }) + busted.subscribe({ 'suite', 'reinitialize' }, handler.baseSuiteRepeat, { priority = 1 }) busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart, { priority = 1 }) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd, { priority = 1 }) busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 730df2c4..fcbd9191 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -4,29 +4,55 @@ local string = require("string") return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) - local xml_doc - local suiteStartTime - - handler.suiteStart = function() - suiteStartTime = socket.gettime() - xml_doc = xml.new('testsuite', { + local top = { + start_time = socket.gettime(), + xml_doc = xml.new('testsuites', { tests = 0, errors = 0, failures = 0, skip = 0, }) + } + local stack = {} + + handler.suiteStart = function(count, total) + local suite = { + start_time = socket.gettime(), + xml_doc = xml.new('testsuite', { + name = 'Run ' .. count .. ' of ' .. total, + tests = 0, + errors = 0, + failures = 0, + skip = 0, + }) + } + top.xml_doc:add_direct_child(suite.xml_doc) + table.insert(stack, top) + top = suite return nil, true end - local function now() - return string.format("%.2f", (socket.gettime() - suiteStartTime)) + local function elapsed(start_time) + return string.format("%.2f", (socket.gettime() - start_time)) end - handler.suiteEnd = function() - xml_doc.attr.time = now() + handler.suiteEnd = function(count, total) + local suite = top + suite.xml_doc.attr.time = elapsed(suite.start_time) + + top = table.remove(stack) + top.xml_doc.attr.tests = top.xml_doc.attr.tests + suite.xml_doc.attr.tests + top.xml_doc.attr.errors = top.xml_doc.attr.errors + suite.xml_doc.attr.errors + top.xml_doc.attr.failures = top.xml_doc.attr.failures + suite.xml_doc.attr.failures + top.xml_doc.attr.skip = top.xml_doc.attr.skip + suite.xml_doc.attr.skip + + return nil, true + end - print(xml.tostring(xml_doc, '', '\t', nil, false)) + handler.exit = function() + top.xml_doc.attr.time = elapsed(top.start_time) + print(xml.tostring(top.xml_doc, '', '\t', nil, false)) return nil, true end @@ -35,9 +61,9 @@ return function(options, busted) local testcase_node = xml.new('testcase', { classname = element.trace.short_src .. ':' .. element.trace.currentline, name = handler.getFullName(element), - time = now() + time = elapsed(testStartTime) }) - xml_doc:add_direct_child(testcase_node) + top.xml_doc:add_direct_child(testcase_node) if status ~= 'success' then testcase_node:addtag(status) @@ -47,13 +73,19 @@ return function(options, busted) end end + handler.testStart = function(element, parent) + testStartTime = socket.gettime() + + return nil, true + end + handler.testEnd = function(element, parent, status) - xml_doc.attr.tests = xml_doc.attr.tests + 1 + top.xml_doc.attr.tests = top.xml_doc.attr.tests + 1 if status == 'success' then testStatus(element, parent, nil, 'success') elseif status == 'pending' then - xml_doc.attr.skip = xml_doc.attr.skip + 1 + top.xml_doc.attr.skip = top.xml_doc.attr.skip + 1 local formatted = handler.inProgress[tostring(element)] or {} testStatus(element, parent, formatted.message, 'skipped', formatted.trace) end @@ -62,33 +94,35 @@ return function(options, busted) end handler.failureTest = function(element, parent, message, trace) - xml_doc.attr.failures = xml_doc.attr.failures + 1 + top.xml_doc.attr.failures = top.xml_doc.attr.failures + 1 testStatus(element, parent, message, 'failure', trace) return nil, true end handler.errorTest = function(element, parent, message, trace) - xml_doc.attr.errors = xml_doc.attr.errors + 1 + top.xml_doc.attr.errors = top.xml_doc.attr.errors + 1 testStatus(element, parent, message, 'error', trace) return nil, true end handler.error = function(element, parent, message, trace) if element.descriptor ~= 'it' then - xml_doc.attr.errors = xml_doc.attr.errors + 1 - xml_doc:addtag('error') - xml_doc:text(message) + top.xml_doc.attr.errors = top.xml_doc.attr.errors + 1 + top.xml_doc:addtag('error') + top.xml_doc:text(message) if trace and trace.traceback then - xml_doc:text(trace.traceback) + top.xml_doc:text(trace.traceback) end - xml_doc:up() + top.xml_doc:up() end return nil, true end + busted.subscribe({ 'exit' }, handler.exit) busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) + busted.subscribe({ 'test', 'start' }, handler.testStart, { predicate = handler.cancelOnPending }) busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'error', 'it' }, handler.errorTest) busted.subscribe({ 'failure', 'it' }, handler.failureTest) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 6c48a82e..fc4b092f 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -128,6 +128,12 @@ return function(options, busted) return nil, true end + handler.suiteStart = function(count, total) + local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') + io.write(runString:format(count, total)) + io.flush() + end + handler.suiteEnd = function() print('') print(statusString()) @@ -158,6 +164,7 @@ return function(options, busted) end busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) busted.subscribe({ 'failure', 'file' }, handler.error) diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index b66e0329..f34015cc 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -129,7 +129,13 @@ return function(options, busted) return nil, true end - handler.suiteEnd = function() + handler.suiteStart = function(count, total) + local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') + io.write(runString:format(count, total)) + io.flush() + end + + handler.suiteEnd = function(count, total) print('') print(statusString()) @@ -159,6 +165,7 @@ return function(options, busted) end busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'suite', 'start' }, handler.suiteStart) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) busted.subscribe({ 'error', 'file' }, handler.error) busted.subscribe({ 'failure', 'file' }, handler.error) diff --git a/busted/runner.lua b/busted/runner.lua index 6085688e..4b648c22 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -323,7 +323,7 @@ return function(options) getmetatable(file.run).__call = info.func end - busted.subscribe({'suite', 'repeat'}, function() + busted.subscribe({'suite', 'reinitialize'}, function() local oldctx = busted.context.get() local children = busted.context.children(oldctx) @@ -346,23 +346,22 @@ return function(options) end) local runs = tonumber(cliArgs['repeat']) or 1 - local runString = (runs > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') for i = 1, runs do - io.write(runString:format(i, runs)) - io.flush() if i > 1 then - busted.publish({ 'suite', 'repeat' }) + busted.publish({ 'suite', 'reinitialize' }) end - busted.publish({ 'suite', 'start' }) + busted.publish({ 'suite', 'start' }, i, runs) busted.execute() - busted.publish({ 'suite', 'end' }) + busted.publish({ 'suite', 'end' }, i, runs) if quitOnError and (failures > 0 or errors > 0) then break end end + busted.publish({ 'exit' }) + local exit = 0 if failures > 0 or errors > 0 then exit = failures + errors From e986cb6ed796741e7da0b13eeb7dfe014638a1ae Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 21 Feb 2015 16:15:55 -0800 Subject: [PATCH 123/293] Base output handler runs first Make sure the base output handler's subscribers run before the derived output handler's subscribers by setting the subscription priority to 1 for all base output handler subscriptions. --- busted/outputHandlers/base.lua | 14 +++++++------- busted/outputHandlers/junit.lua | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index c380d9e0..5ea9540f 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -26,13 +26,13 @@ return function(busted) busted.subscribe({ 'suite', 'reinitialize' }, handler.baseSuiteRepeat, { priority = 1 }) busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart, { priority = 1 }) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd, { priority = 1 }) - busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { predicate = handler.cancelOnPending }) - busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { predicate = handler.cancelOnPending }) - busted.subscribe({ 'pending' }, handler.basePending, { predicate = handler.cancelOnPending }) - busted.subscribe({ 'failure', 'it' }, handler.baseTestFailure) - busted.subscribe({ 'error', 'it' }, handler.baseTestError) - busted.subscribe({ 'failure' }, handler.baseError) - busted.subscribe({ 'error' }, handler.baseError) + busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { priority = 1, predicate = handler.cancelOnPending }) + busted.subscribe({ 'test', 'end' }, handler.baseTestEnd, { priority = 1, predicate = handler.cancelOnPending }) + busted.subscribe({ 'pending' }, handler.basePending, { priority = 1, predicate = handler.cancelOnPending }) + busted.subscribe({ 'failure', 'it' }, handler.baseTestFailure, { priority = 1 }) + busted.subscribe({ 'error', 'it' }, handler.baseTestError, { priority = 1 }) + busted.subscribe({ 'failure' }, handler.baseError, { priority = 1 }) + busted.subscribe({ 'error' }, handler.baseError, { priority = 1 }) end handler.getFullName = function(context) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index fcbd9191..0d9aa864 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -86,8 +86,9 @@ return function(options, busted) testStatus(element, parent, nil, 'success') elseif status == 'pending' then top.xml_doc.attr.skip = top.xml_doc.attr.skip + 1 - local formatted = handler.inProgress[tostring(element)] or {} - testStatus(element, parent, formatted.message, 'skipped', formatted.trace) + local formatted = handler.pendings[#handler.pendings] + local trace = element.trace ~= formatted.trace and formatted.trace + testStatus(element, parent, formatted.message, 'skipped', trace) end return nil, true From 0cb016ffb79babca2cf1ac78d3dbe4b075bcf0a2 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 18 Feb 2015 15:59:32 -0800 Subject: [PATCH 124/293] Add a helper loader module --- busted/modules/helper_loader.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 busted/modules/helper_loader.lua diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua new file mode 100644 index 00000000..b53f91ad --- /dev/null +++ b/busted/modules/helper_loader.lua @@ -0,0 +1,19 @@ +local utils = require 'busted.utils' + +return function() + local loadHelper = function(helper, hpath, options) + local success, err = pcall(function() + if helper:match('%.lua$') or helper:match('%.moon$') then + dofile(utils.normpath(hpath)) + else + require(helper) + end + end) + + if not success then + busted.publish({ 'error', 'helper' }, { descriptor = 'helper', name = helper }, nil, err, {}) + end + end + + return loadHelper +end From c26c28e1d7bdb01c66db4b165b8d98de29c19e56 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 19 Feb 2015 01:25:25 -0800 Subject: [PATCH 125/293] Use helper loader module to load helper script --- busted/modules/helper_loader.lua | 2 +- busted/runner.lua | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index b53f91ad..e633beae 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -1,7 +1,7 @@ local utils = require 'busted.utils' return function() - local loadHelper = function(helper, hpath, options) + local loadHelper = function(helper, hpath, options, busted) local success, err = pcall(function() if helper:match('%.lua$') or helper:match('%.moon$') then dofile(utils.normpath(hpath)) diff --git a/busted/runner.lua b/busted/runner.lua index 6085688e..1989fa31 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -14,6 +14,7 @@ return function(options) local busted = require 'busted.core'() local configLoader = require 'busted.modules.configuration_loader'() + local helperLoader = require 'busted.modules.helper_loader'() local outputHandlerLoader = require 'busted.modules.output_handler_loader'() local luacov = require 'busted.modules.luacov'() @@ -138,7 +139,13 @@ return function(options) end if cliArgs.helper ~= '' then - dofile(cliArgs.helper) + local helperOptions = { + verbose = cliArgs.verbose, + language = cliArgs.lang, + } + + local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) + helperLoader(cliArgs.helper, hpath, helperOptions, busted) end local loaders = {} From 5be57fd49d26be1132b9ac73ed296c65574016e6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 20 Feb 2015 22:09:50 -0800 Subject: [PATCH 126/293] Output error when helper script fails to load --- busted/runner.lua | 29 ++++++++++++++++------------- spec/cl_spec.lua | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 1989fa31..5676e824 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -138,16 +138,6 @@ return function(options) package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') end - if cliArgs.helper ~= '' then - local helperOptions = { - verbose = cliArgs.verbose, - language = cliArgs.lang, - } - - local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) - helperLoader(cliArgs.helper, hpath, helperOptions, busted) - end - local loaders = {} if #cliArgs.loaders > 0 then string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) @@ -171,16 +161,18 @@ return function(options) local errors = 0 local quitOnError = cliArgs['no-keep-going'] - busted.subscribe({ 'error' }, function(element, parent, status) + busted.subscribe({ 'error' }, function(element, parent, message) if element.descriptor == 'output' then - print('Cannot load output library: ' .. element.name) + print('Cannot load output library: ' .. element.name .. '\n' .. message) + elseif element.descriptor == 'helper' then + print('Cannot load helper script: ' .. element.name .. '\n' .. message) end errors = errors + 1 busted.skipAll = quitOnError return nil, true end) - busted.subscribe({ 'failure' }, function(element, parent, status) + busted.subscribe({ 'failure' }, function(element, parent, message) if element.descriptor == 'it' then failures = failures + 1 else @@ -305,6 +297,17 @@ return function(options) applyFilter({ 'it', 'pending' } , 'tags' , filterTags ) applyFilter({ 'describe', 'it', 'pending' }, 'exclude-tags', filterExcludeTags) + -- Set up helper script + if cliArgs.helper ~= '' then + local helperOptions = { + verbose = cliArgs.verbose, + language = cliArgs.lang, + } + + local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) + helperLoader(cliArgs.helper, hpath, helperOptions, busted) + end + -- Set up test loader options local testFileLoaderOptions = { verbose = cliArgs.verbose, diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 51d11ae7..8a1b292c 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -481,6 +481,30 @@ describe('Tests error messages through the command line', function() error_end() end) + it('when helper script not found', function() + error_start() + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here') + local err = result:match('Error → .-:%d+: (.-)\n') + local errmsg = result:match('(.-)\n') + local expectedErr = "module 'not_found_here' not found:" + local expectedMsg = 'Cannot load helper script: not_found_here' + assert.is_equal(expectedErr, err) + assert.is_equal(expectedMsg, errmsg) + error_end() + end) + + it('when helper lua script not found', function() + error_start() + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua') + local err = result:match('Error → (.-)\n') + local errmsg = result:match('(.-)\n') + local expectedErr = 'cannot open ./not_found_here.lua: No such file or directory' + local expectedMsg = 'Cannot load helper script: not_found_here.lua' + assert.is_equal(normpath(expectedErr), err) + assert.is_equal(expectedMsg, errmsg) + error_end() + end) + it('when no test files matching Lua pattern', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') From 01107b38c987fc885678e4b6e1c5a9aa6f3d9541 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 19 Feb 2015 00:44:18 -0800 Subject: [PATCH 127/293] Support loading helper moonscript files --- busted/modules/helper_loader.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index e633beae..517980f5 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -1,10 +1,13 @@ local utils = require 'busted.utils' +local hasMoon, moonscript = pcall(require, 'moonscript') return function() local loadHelper = function(helper, hpath, options, busted) local success, err = pcall(function() - if helper:match('%.lua$') or helper:match('%.moon$') then + if helper:match('%.lua$') then dofile(utils.normpath(hpath)) + elseif hasMoon and helper:match('%.moon$') then + moonscript.dofile(utils.normpath(hpath)) else require(helper) end From a7ca1e423489477b2171aa4bec1d7a2f3ce3d6ef Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 19 Feb 2015 12:48:02 -0800 Subject: [PATCH 128/293] Forward command-line options to helper script Add command-line option to forward options to the helper script. Use the `-Xhelper` option to pass options to the helper script. If the argument to `-Xhelper` contains comas, then it is split into multiple options at the commas. --- busted/modules/helper_loader.lua | 1 + busted/runner.lua | 2 ++ spec/cl_helper_script.lua | 20 ++++++++++++++++++++ spec/cl_spec.lua | 19 +++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 spec/cl_helper_script.lua diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index 517980f5..166f7ccd 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -4,6 +4,7 @@ local hasMoon, moonscript = pcall(require, 'moonscript') return function() local loadHelper = function(helper, hpath, options, busted) local success, err = pcall(function() + arg = options.arguments if helper:match('%.lua$') then dofile(utils.normpath(hpath)) elseif hasMoon and helper:match('%.moon$') then diff --git a/busted/runner.lua b/busted/runner.lua index 5676e824..88be3c57 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -60,6 +60,7 @@ return function(options) cli:add_option('--helper=PATH', 'A helper script that is run before tests') cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.') + cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.') cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') cli:add_flag('-v, --verbose', 'verbose output of errors') @@ -302,6 +303,7 @@ return function(options) local helperOptions = { verbose = cliArgs.verbose, language = cliArgs.lang, + arguments = utils.split(cliArgs.Xhelper, ',') or {} } local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) diff --git a/spec/cl_helper_script.lua b/spec/cl_helper_script.lua new file mode 100644 index 00000000..0f91e536 --- /dev/null +++ b/spec/cl_helper_script.lua @@ -0,0 +1,20 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +local before_each = require 'busted'.before_each +local after_each = require 'busted'.after_each +local assert = require 'busted'.assert +local cli = require 'cliargs' + +cli:set_name('cl_helper_script') +cli:add_flag('--fail-before-each', 'force before each to fail') +cli:add_flag('--fail-after-each', 'force after each to fail') + +local cliArgs = cli:parse(arg) + +before_each(function() + assert(not cliArgs['fail-before-each']) +end) + +after_each(function() + assert(not cliArgs['fail-after-each']) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 8a1b292c..d6b9d5bd 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -706,3 +706,22 @@ describe('Tests Xoutput commandline option', function() assert.is_equal('10:17:36', timestamp) end) end) + +describe('Tests Xhelper commandline option', function() + it('forwards no options to helper script when no options specified', function() + local success = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua --pattern=cl_success.lua$') + assert.is_true(success) + end) + + it('forwards single option to helper script', function() + local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" --pattern=cl_success.lua$') + assert.is_false(success) + assert.is_equal(1, exitcode) + end) + + it('forwards multiple options to helper script', function() + local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each,--fail-after-each" --pattern=cl_success.lua$') + assert.is_false(success) + assert.is_equal(2, exitcode) + end) +end) From 0c0581e81d702f1ab444836ee6f22cd9133dd79d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 19 Feb 2015 13:36:09 -0800 Subject: [PATCH 129/293] Add auto-completion function for -Xhelper --- completions/bash/busted.bash | 3 ++- completions/zsh/_busted | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index be35962b..c344bf6b 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -101,7 +101,7 @@ _busted() { _filedir -d return 0 ;; - -Xoutput) + -Xoutput|--Xhelper) # no completion available return 0 ;; @@ -136,6 +136,7 @@ _busted() { -c --coverage -s --enable-sound -Xoutput + -Xhelper --no-keep-going --no-recurse --shuffle --shuffle-tests --shuffle-files diff --git a/completions/zsh/_busted b/completions/zsh/_busted index d63a4d91..8bd00e62 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -24,6 +24,7 @@ _busted_args=( "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" "-Xoutput[Pass 'OPTION' as an option to the output handler. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" +"-Xhelper[Pass 'OPTION' as an option to the helper script. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" "(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" "(-d --cwd)"{-d,--cwd=}"[Path to current working directory (default: ./)]:directory:_dirs" "(-h --help)"{-h,--help}"[Help]" From 0e8218f96491b5dd003a41278a4ea4b15c3cd2eb Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 20 Feb 2015 01:51:38 -0800 Subject: [PATCH 130/293] Fix variables used before they are initialized --- busted/init.lua | 1 + busted/outputHandlers/sound.lua | 4 +- busted/utils.lua | 66 +++++++++++++++++---------------- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index aa608144..11fd9875 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -132,6 +132,7 @@ local function init(busted) end local it = function(element) + local parent = busted.context.parent(element) local finally local parent = busted.context.parent(element) diff --git a/busted/outputHandlers/sound.lua b/busted/outputHandlers/sound.lua index 973e7486..8ac1a46c 100644 --- a/busted/outputHandlers/sound.lua +++ b/busted/outputHandlers/sound.lua @@ -1,9 +1,11 @@ +local app = require 'pl.app' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) local language = require('busted.languages.' .. options.language) handler.suiteEnd = function() - local system, sayer_pre, sayer_post + local system = app.platform() + local sayer_pre, sayer_post local messages if system == 'Linux' then diff --git a/busted/utils.lua b/busted/utils.lua index 5f67b1ac..4e02bc03 100644 --- a/busted/utils.lua +++ b/busted/utils.lua @@ -2,41 +2,43 @@ local path = require 'pl.path' math.randomseed(os.time()) +-- Do not use pl.path.normpath +-- It is broken for paths with leading '../../' +local function normpath(fpath) + if type(fpath) ~= 'string' then + error(fpath .. ' is not a string') + end + local sep = '/' + if path.is_windows then + sep = '\\' + if fpath:match '^\\\\' then -- UNC + return '\\\\' .. normpath(fpath:sub(3)) + end + fpath = fpath:gsub('/','\\') + end + local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' + local np_pat1 = np_gen1:gsub('SEP', sep) + local np_pat2 = np_gen2:gsub('SEP', sep) + local k + repeat -- /./ -> / + fpath, k = fpath:gsub(np_pat2, sep) + until k == 0 + repeat -- A/../ -> (empty) + local oldpath = fpath + fpath, k = fpath:gsub(np_pat1, function(d, up) + if d == '..' then return nil end + if d == '.' then return up end + return '' + end) + until k == 0 or oldpath == fpath + if fpath == '' then fpath = '.' end + return fpath +end + return { split = require 'pl.utils'.split, - -- Do not use pl.path.normpath - -- It is broken for paths with leading '../../' - normpath = function(fpath) - if type(fpath) ~= 'string' then - error(fpath .. ' is not a string') - end - local sep = '/' - if path.is_windows then - sep = '\\' - if fpath:match '^\\\\' then -- UNC - return '\\\\' .. normpath(fpath:sub(3)) - end - fpath = fpath:gsub('/','\\') - end - local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' - local np_pat1 = np_gen1:gsub('SEP', sep) - local np_pat2 = np_gen2:gsub('SEP', sep) - local k - repeat -- /./ -> / - fpath, k = fpath:gsub(np_pat2, sep) - until k == 0 - repeat -- A/../ -> (empty) - local oldpath = fpath - fpath, k = fpath:gsub(np_pat1, function(d, up) - if d == '..' then return nil end - if d == '.' then return up end - return '' - end) - until k == 0 or oldpath == fpath - if fpath == '' then fpath = '.' end - return fpath - end, + normpath = normpath, shuffle = function(t, seed) if seed then math.randomseed(seed) end From 57ca3b3e00fc63bb575c0f37dc3af9988c7df141 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 23 Feb 2015 10:51:34 -0800 Subject: [PATCH 131/293] Fix duplicate parent variable --- busted/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/busted/init.lua b/busted/init.lua index 11fd9875..da052f50 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -134,7 +134,6 @@ local function init(busted) local it = function(element) local parent = busted.context.parent(element) local finally - local parent = busted.context.parent(element) busted.publish({ 'test', 'start' }, element, parent) From f2e3e983e8b2039d41fac463f8e3450f991d6d6d Mon Sep 17 00:00:00 2001 From: mpeterv Date: Mon, 23 Feb 2015 23:09:20 +0300 Subject: [PATCH 132/293] Add a missing module to rockspec --- busted-2.0.rc6-0.rockspec | 1 + 1 file changed, 1 insertion(+) diff --git a/busted-2.0.rc6-0.rockspec b/busted-2.0.rc6-0.rockspec index d11054fa..30cce7c9 100644 --- a/busted-2.0.rc6-0.rockspec +++ b/busted-2.0.rc6-0.rockspec @@ -46,6 +46,7 @@ build = { ['busted.modules.luacov'] = 'busted/modules/luacov.lua', ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', + ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', From 63f609dbfd0977f0bdda3f27ed8578b877db8cf6 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Tue, 27 Jan 2015 20:21:43 -0800 Subject: [PATCH 133/293] add scm rockspec mention rockspec update scm rockspec to latest --- .travis.yml | 2 +- busted-scm-0.rockspec | 79 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 busted-scm-0.rockspec diff --git a/.travis.yml b/.travis.yml index 4f9eeebb..f53b5bba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: - sudo luarocks install lua-ev scm --server=http://luarocks.org/repositories/rocks-scm/ - sudo luarocks install copas - sudo luarocks install moonscript - - sudo luarocks make + - sudo luarocks make busted-scm-0.rockspec script: busted diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec new file mode 100644 index 00000000..bf2c4f07 --- /dev/null +++ b/busted-scm-0.rockspec @@ -0,0 +1,79 @@ +package = 'busted' +version = 'scm-0' +source = { + url = "git://github.com/Olivine-Labs/busted", + branch = "master" +} +description = { + summary = 'Elegant Lua unit testing.', + detailed = [[ + An elegant, extensible, testing framework. + Ships with a large amount of useful asserts, + plus the ability to write your own. Output + in pretty or plain terminal format, JSON, + or TAP for CI integration. Great for TDD + and unit, integration, and functional tests. + ]], + homepage = 'http://olivinelabs.com/busted/', + license = 'MIT ' +} +dependencies = { + 'lua >= 5.1', + 'lua_cliargs >= 2.3-0', + 'luafilesystem >= 1.5.0', + 'dkjson >= 2.1.0', + 'say >= 1.2-1', + 'luassert >= 1.7.4-0', + 'ansicolors >= 1.0-1', + 'lua-term >= 0.1-1', + 'penlight >= 1.0.0-1', + 'mediator_lua >= 1.1-3', +} +build = { + type = 'builtin', + modules = { + ['busted.core'] = 'busted/core.lua', + ['busted.context'] = 'busted/context.lua', + ['busted.environment'] = 'busted/environment.lua', + ['busted.compatibility'] = 'busted/compatibility.lua', + ['busted.done'] = 'busted/done.lua', + ['busted.runner'] = 'busted/runner.lua', + ['busted.status'] = 'busted/status.lua', + ['busted.utils'] = 'busted/utils.lua', + ['busted.init'] = 'busted/init.lua', + + ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', + ['busted.modules.luacov'] = 'busted/modules/luacov.lua', + ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', + ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', + ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', + + ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', + ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', + ['busted.modules.files.terra'] = 'busted/modules/files/terra.lua', + + ['busted.outputHandlers.base'] = 'busted/outputHandlers/base.lua', + ['busted.outputHandlers.utfTerminal'] = 'busted/outputHandlers/utfTerminal.lua', + ['busted.outputHandlers.plainTerminal'] = 'busted/outputHandlers/plainTerminal.lua', + ['busted.outputHandlers.TAP'] = 'busted/outputHandlers/TAP.lua', + ['busted.outputHandlers.json'] = 'busted/outputHandlers/json.lua', + ['busted.outputHandlers.junit'] = 'busted/outputHandlers/junit.lua', + ['busted.outputHandlers.sound'] = 'busted/outputHandlers/sound.lua', + + ['busted.languages.en'] = 'busted/languages/en.lua', + ['busted.languages.ar'] = 'busted/languages/ar.lua', + ['busted.languages.de'] = 'busted/languages/de.lua', + ['busted.languages.fr'] = 'busted/languages/fr.lua', + ['busted.languages.ja'] = 'busted/languages/ja.lua', + ['busted.languages.nl'] = 'busted/languages/nl.lua', + ['busted.languages.ru'] = 'busted/languages/ru.lua', + ['busted.languages.th'] = 'busted/languages/th.lua', + ['busted.languages.ua'] = 'busted/languages/ua.lua', + ['busted.languages.zh'] = 'busted/languages/zh.lua', + }, + install = { + bin = { + ['busted'] = 'bin/busted' + } + } +} From cd53b799332d933f28b93f3b29d6046783afc970 Mon Sep 17 00:00:00 2001 From: Boris Nagaev Date: Tue, 24 Feb 2015 02:24:18 +0300 Subject: [PATCH 134/293] fix memoryleak in userdata on os.exit in Lua 5.1 Not calling os.exit results in running a code twice in standalone mode. Function compatibility.osexit runs collectgarbage() while value of collectgarbage('count') (which is memory usage) changes. --- busted/compatibility.lua | 28 +++++++++++++++++++++++++++- busted/runner.lua | 10 ++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 78caf36e..7837656f 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -30,5 +30,31 @@ return { if f ~= 0 then return f end end, - unpack = table.unpack or unpack + unpack = table.unpack or unpack, + + osexit = function(code, close) + if close and _VERSION == 'Lua 5.1' then + -- From Lua 5.1 manual: + -- > The userdata itself is freed only in the next + -- > garbage-collection cycle. + -- Call collectgarbage() while collectgarbage('count') + -- changes + 3 times, at least 3 times, + -- at max 100 times (to prevent infinite loop). + local times_const = 0 + for i = 1, 100 do + local count_before = collectgarbage("count") + collectgarbage() + local count_after = collectgarbage("count") + if count_after == count_before then + times_const = times_const + 1 + if times_const > 3 then + break + end + else + times_const = 0 + end + end + end + os.exit(code, close) + end, } diff --git a/busted/runner.lua b/busted/runner.lua index b0212270..0d49198c 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -19,6 +19,8 @@ return function(options) local luacov = require 'busted.modules.luacov'() + local osexit = require 'busted.compatibility'.osexit + require 'busted'(busted) -- Default cli arg values @@ -80,13 +82,13 @@ return function(options) -- Parse the cli arguments local cliArgs = cli:parse(arg) if not cliArgs then - os.exit(1, true) + osexit(1, true) end -- Return early if only asked for the version if cliArgs.version then print(busted.version) - os.exit(0, true) + osexit(0, true) end -- Load current working directory @@ -152,7 +154,7 @@ return function(options) for _, included in pairs(tags) do if excluded == included then print('Cannot use --tags and --exclude-tags for the same tags') - os.exit(1, true) + osexit(1, true) end end end @@ -381,5 +383,5 @@ return function(options) exit = 255 end end - os.exit(exit, true) + osexit(exit, true) end From 5f660608a9e8dd06dc8c989f117d2aa3454443ec Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 09:30:05 -0800 Subject: [PATCH 135/293] Insert junit timestamp in each test suite Insert timestamp in each test suite header instead of the overall header for all test suites. --- busted/outputHandlers/junit.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 84578a72..36e78936 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -11,10 +11,10 @@ return function(options, busted) errors = 0, failures = 0, skip = 0, - timestamp = os.date('!%Y-%m-%dT%T'), }) } local stack = {} + local testStartTime handler.suiteStart = function(count, total) local suite = { @@ -25,6 +25,7 @@ return function(options, busted) errors = 0, failures = 0, skip = 0, + timestamp = os.date('!%Y-%m-%dT%T'), }) } top.xml_doc:add_direct_child(suite.xml_doc) From 4b64385a572eb349ae00a4f52812a2be142f71f4 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 01:27:28 -0800 Subject: [PATCH 136/293] Fix configuration loading This updates the configuration loader to merge command-line options with a specified configuration task, taking in order of precedence: 1. Options specified on the command-line 2. Options specified in the configuration file 3. Built-in command-line option defaults --- busted/modules/configuration_loader.lua | 10 +- busted/runner.lua | 103 +++++++++++---------- spec/modules/configuration_loader_spec.lua | 34 ++++++- 3 files changed, 91 insertions(+), 56 deletions(-) diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index 83b5cef6..f437a04c 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -2,28 +2,30 @@ return function() local tablex = require 'pl.tablex' -- Function to load the .busted configuration file if available - local loadBustedConfigurationFile = function(configFile, config) + local loadBustedConfigurationFile = function(configFile, config, defaults) if type(configFile) ~= 'table' then return config, '.busted file does not return a table.' end - local run = config.run + local defaults = defaults or {} + local run = config.run or defaults.run if run and run ~= '' then local runConfig = configFile[run] if type(runConfig) == 'table' then config = tablex.merge(runConfig, config, true) - return config else return config, 'Task `' .. run .. '` not found, or not a table.' end end - if configFile and type(configFile.default) == 'table' then + if type(configFile.default) == 'table' then config = tablex.merge(configFile.default, config, true) end + config = tablex.merge(defaults, config, true) + return config end diff --git a/busted/runner.lua b/busted/runner.lua index 0d49198c..bbd6727a 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -36,48 +36,61 @@ return function(options) local source = info.source local fileName = source:sub(1,1) == '@' and source:sub(2) or source + local cliArgsParsed = {} + local function processOption(key, value, altkey, opt) + if altkey then cliArgsParsed[altkey] = value end + cliArgsParsed[key] = value + return true + end + + local function processVersion() + -- Return early if asked for the version + print(busted.version) + osexit(0, true) + end + -- Load up the command-line interface options cli:set_name(path.basename(fileName)) - cli:add_flag('--version', 'prints the program version and exits') + cli:add_flag('--version', 'prints the program version and exits', processVersion) if isBatch then cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1) - cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern) + cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) end - cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput) - cli:add_option('-d, --cwd=cwd', 'path to current working directory', './') - cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags') - cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags') - cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern') - cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter') - cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix) - cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix) - cli:add_option('-r, --run=RUN', 'config to run from .busted file') - cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1') - cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed) - cli:add_option('--lang=LANG', 'language for error messages', 'en') - cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders) - cli:add_option('--helper=PATH', 'A helper script that is run before tests') - - cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.') - cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.') - - cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)') - cli:add_flag('-v, --verbose', 'verbose output of errors') - cli:add_flag('-s, --enable-sound', 'executes `say` command if available') - cli:add_flag('--no-keep-going', 'quit after first error or failure') - cli:add_flag('--no-recurse', 'do not recurse into subdirectories') - cli:add_flag('--list', 'list the names of all tests instead of running them') - cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)') - cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files') - cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests') - cli:add_flag('--sort', 'sort file and test order (--sort-tests and --sort-files)') - cli:add_flag('--sort-files', 'sort file execution order') - cli:add_flag('--sort-tests', 'sort test order within a file') - cli:add_flag('--suppress-pending', 'suppress `pending` test output') - cli:add_flag('--defer-print', 'defer print to when test suite is complete') + cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) + cli:add_option('-d, --cwd=cwd', 'path to current working directory', './', processOption) + cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', nil, processOption) + cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', nil, processOption) + cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', nil, processOption) + cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', nil, processOption) + cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processOption) + cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processOption) + cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) + cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', nil, processOption) + cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processOption) + cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) + cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processOption) + cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) + + cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', nil, processOption) + cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', nil, processOption) + + cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', processOption) + cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) + cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) + cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) + cli:add_flag('--no-recurse', 'do not recurse into subdirectories', processOption) + cli:add_flag('--list', 'list the names of all tests instead of running them', processOption) + cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) + cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) + cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) + cli:add_flag('--sort', 'sort file and test order (--sort-tests and --sort-files)', processOption) + cli:add_flag('--sort-files', 'sort file execution order', processOption) + cli:add_flag('--sort-tests', 'sort test order within a file', processOption) + cli:add_flag('--suppress-pending', 'suppress `pending` test output', processOption) + cli:add_flag('--defer-print', 'defer print to when test suite is complete', processOption) -- Parse the cli arguments local cliArgs = cli:parse(arg) @@ -85,14 +98,8 @@ return function(options) osexit(1, true) end - -- Return early if only asked for the version - if cliArgs.version then - print(busted.version) - osexit(0, true) - end - -- Load current working directory - local fpath = utils.normpath(cliArgs.d) + local fpath = utils.normpath(cliArgs.cwd) -- Load busted config file if available local configFile = { } @@ -101,7 +108,7 @@ return function(options) local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) if bustedConfigFile then - local config, err = configLoader(configFile, cliArgs) + local config, err = configLoader(configFile, cliArgsParsed, cliArgs) if err then print(err) @@ -113,11 +120,11 @@ return function(options) local tags = {} local excludeTags = {} - if cliArgs.t ~= '' then - tags = utils.split(cliArgs.t, ',') + if cliArgs.tags and cliArgs.tags ~= '' then + tags = utils.split(cliArgs.tags, ',') end - if cliArgs['exclude-tags'] ~= '' then + if cliArgs['exclude-tags'] and cliArgs['exclude-tags'] ~= '' then excludeTags = utils.split(cliArgs['exclude-tags'], ',') end @@ -203,11 +210,11 @@ return function(options) arguments = utils.split(cliArgs.Xoutput, ',') or {} } - local opath = utils.normpath(path.join(fpath, cliArgs.o)) - local outputHandler = outputHandlerLoader(cliArgs.o, opath, outputHandlerOptions, busted, defaultOutput) + local opath = utils.normpath(path.join(fpath, cliArgs.output)) + local outputHandler = outputHandlerLoader(cliArgs.output, opath, outputHandlerOptions, busted, defaultOutput) outputHandler:subscribe(outputHandlerOptions) - if cliArgs.s then + if cliArgs['enable-sound'] then require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) end diff --git a/spec/modules/configuration_loader_spec.lua b/spec/modules/configuration_loader_spec.lua index e93cc7ef..c5de45b1 100644 --- a/spec/modules/configuration_loader_spec.lua +++ b/spec/modules/configuration_loader_spec.lua @@ -1,18 +1,19 @@ describe('Config Loader', function() local configLoader = require 'busted.modules.configuration_loader'() - local testConfig, cliArgs + local testConfig, cliArgs, defaults before_each(function() testConfig = { default = { - output = { 'utfTerminal' } + output = 'utfTerminal' }, windows = { - output = { 'plainTerminal' } + output = 'plainTerminal' } } cliArgs = { } + defaults = { } end) it('returns a valid config with no config file', function() @@ -38,8 +39,33 @@ describe('Config Loader', function() assert.are.equal(nil, err) end) + it('returns a valid config with specified config and defaults specified', function() + defaults = { output = 'TAP' } + cliArgs.run = 'windows' + local config, err = configLoader(testConfig, cliArgs, defaults) + + assert.are.same(testConfig.windows.output, config.output) + assert.are.equal(nil, err) + end) + + it('returns a valid config with cliArgs and defaults specified', function() + cliArgs = { output = 'TAP' } + local config, err = configLoader(testConfig, cliArgs, defaults) + + assert.are.same(cliArgs, config) + assert.are.equal(nil, err) + end) + + it('returns a valid config with defaults if no configs present', function() + defaults = { output = 'TAP' } + local config, err = configLoader({}, {}, defaults) + + assert.are.same(defaults, config) + assert.are.equal(nil, err) + end) + it('returns an error with an invalid config', function() - local config, err = configLoader('invalid', cliArgs, 'run') + local config, err = configLoader('invalid', cliArgs) assert.are_not.equal(nil, err) end) From 69231510f81f1f1a76fc57dfd4d8697547648c7c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 13:46:57 -0800 Subject: [PATCH 137/293] Exit if error loading configuration --- busted/runner.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index bbd6727a..398a9293 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -104,14 +104,12 @@ return function(options) -- Load busted config file if available local configFile = { } local bustedConfigFilePath = utils.normpath(path.join(fpath, '.busted')) - local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) - if bustedConfigFile then local config, err = configLoader(configFile, cliArgsParsed, cliArgs) - if err then print(err) + osexit(1, true) else cliArgs = config end From 01e606670bc6a76a81e525e7dce60277491312cb Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 12:17:28 -0800 Subject: [PATCH 138/293] Update lua_cliargs version dependency --- busted-2.0.rc6-0.rockspec | 2 +- busted-scm-0.rockspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/busted-2.0.rc6-0.rockspec b/busted-2.0.rc6-0.rockspec index 30cce7c9..ea8ae610 100644 --- a/busted-2.0.rc6-0.rockspec +++ b/busted-2.0.rc6-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.3-0', + 'lua_cliargs >= 2.3-3', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.2-1', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index bf2c4f07..4ee5cb25 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.3-0', + 'lua_cliargs >= 2.3-3', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.2-1', From 554a493ea1985715cfd86a8fa863a97539cef460 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 12:54:13 -0800 Subject: [PATCH 139/293] Publish file match error from test file loader --- busted/modules/test_file_loader.lua | 5 +++++ busted/runner.lua | 4 ---- spec/cl_spec.lua | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 87eee455..8850e2d5 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -70,6 +70,11 @@ return function(busted, loaders, options) end end + if #fileList == 0 then + local err = 'No test files found matching Lua pattern: ' .. pattern + busted.publish({ 'error' }, {}, nil, err, {}) + end + return fileList end diff --git a/busted/runner.lua b/busted/runner.lua index 398a9293..cb26de74 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -331,10 +331,6 @@ return function(options) local pattern = cliArgs.pattern local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders, testFileLoaderOptions) local fileList = testFileLoader(rootFile, pattern) - if #fileList == 0 then - print('No test files found matching Lua pattern: ' .. pattern) - errors = errors + 1 - end if not cliArgs.ROOT then local ctx = busted.context.get() diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index d6b9d5bd..baf72758 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -508,7 +508,7 @@ describe('Tests error messages through the command line', function() it('when no test files matching Lua pattern', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') - local errmsg = result:match('(.-)\n') + local errmsg = result:match('Error → (.-)\n') local expected = 'No test files found matching Lua pattern: this_filename_does_simply_not_exist$' assert.is_equal(expected, errmsg) error_end() From 3942ed86c35988acb64f0341dc898d944dfd42bb Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 13:46:00 -0800 Subject: [PATCH 140/293] Prefix error messages with "Error:" --- busted/runner.lua | 27 ++++++++++++++------------- spec/cl_spec.lua | 6 +++--- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index cb26de74..18114b50 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -108,7 +108,7 @@ return function(options) if bustedConfigFile then local config, err = configLoader(configFile, cliArgsParsed, cliArgs) if err then - print(err) + print('Error: ' .. err) osexit(1, true) else cliArgs = config @@ -158,7 +158,7 @@ return function(options) for _, excluded in pairs(excludeTags) do for _, included in pairs(tags) do if excluded == included then - print('Cannot use --tags and --exclude-tags for the same tags') + print('Error: Cannot use --tags and --exclude-tags for the same tags') osexit(1, true) end end @@ -171,9 +171,9 @@ return function(options) busted.subscribe({ 'error' }, function(element, parent, message) if element.descriptor == 'output' then - print('Cannot load output library: ' .. element.name .. '\n' .. message) + print('Error: Cannot load output library: ' .. element.name .. '\n' .. message) elseif element.descriptor == 'helper' then - print('Cannot load helper script: ' .. element.name .. '\n' .. message) + print('Error: Cannot load helper script: ' .. element.name .. '\n' .. message) end errors = errors + 1 busted.skipAll = quitOnError @@ -190,15 +190,6 @@ return function(options) return nil, true end) - -- Set up randomization options - busted.sort = cliArgs['sort-tests'] or cliArgs.sort - busted.randomize = cliArgs['shuffle-tests'] or cliArgs.shuffle - busted.randomseed = tonumber(cliArgs.seed) or os.time() - if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then - print('Argument to --seed must be a number') - errors = errors + 1 - end - -- Set up output handler to listen to events local outputHandlerOptions = { verbose = cliArgs.verbose, @@ -216,6 +207,16 @@ return function(options) require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) end + -- Set up randomization options + busted.sort = cliArgs['sort-tests'] or cliArgs.sort + busted.randomize = cliArgs['shuffle-tests'] or cliArgs.shuffle + busted.randomseed = tonumber(cliArgs.seed) or os.time() + if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then + local err = 'Argument to --seed must be a number' + print('Error: ' .. err) + busted.publish({ 'error' }, {}, nil, err, {}) + end + local getFullName = function(name) local parent = busted.context.get() local names = { name } diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index baf72758..3979247a 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -476,7 +476,7 @@ describe('Tests error messages through the command line', function() error_start() local result = run(busted_cmd .. ' --pattern=cl_two_failures.lua$ --output=not_found_here') local errmsg = result:match('(.-)\n') - local expected = 'Cannot load output library: not_found_here' + local expected = 'Error: Cannot load output library: not_found_here' assert.is_equal(expected, errmsg) error_end() end) @@ -487,7 +487,7 @@ describe('Tests error messages through the command line', function() local err = result:match('Error → .-:%d+: (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = "module 'not_found_here' not found:" - local expectedMsg = 'Cannot load helper script: not_found_here' + local expectedMsg = 'Error: Cannot load helper script: not_found_here' assert.is_equal(expectedErr, err) assert.is_equal(expectedMsg, errmsg) error_end() @@ -499,7 +499,7 @@ describe('Tests error messages through the command line', function() local err = result:match('Error → (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = 'cannot open ./not_found_here.lua: No such file or directory' - local expectedMsg = 'Cannot load helper script: not_found_here.lua' + local expectedMsg = 'Error: Cannot load helper script: not_found_here.lua' assert.is_equal(normpath(expectedErr), err) assert.is_equal(expectedMsg, errmsg) error_end() From d68b3cb1bd0ce6199619af97bbc51b50f4ff99b6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 16:27:44 -0800 Subject: [PATCH 141/293] Validate parsed value for numeric command-line opt Generate an error if a numeric command-line option is not provided for `--seed or `--repeat`. --- busted/runner.lua | 20 +++++++++++++------- spec/cl_spec.lua | 13 +++++++++++-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 18114b50..0ffcf354 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -37,12 +37,23 @@ return function(options) local fileName = source:sub(1,1) == '@' and source:sub(2) or source local cliArgsParsed = {} + local function processOption(key, value, altkey, opt) if altkey then cliArgsParsed[altkey] = value end cliArgsParsed[key] = value return true end + local function processNumber(key, value, altkey, opt) + local number = tonumber(value) + if not number then + return nil, 'argument to ' .. opt:gsub('=.*', '') .. ' must be a number' + end + if altkey then cliArgsParsed[altkey] = number end + cliArgsParsed[key] = number + return true + end + local function processVersion() -- Return early if asked for the version print(busted.version) @@ -68,8 +79,8 @@ return function(options) cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processOption) cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processOption) cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) - cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', nil, processOption) - cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processOption) + cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', processNumber) + cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processNumber) cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processOption) cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) @@ -211,11 +222,6 @@ return function(options) busted.sort = cliArgs['sort-tests'] or cliArgs.sort busted.randomize = cliArgs['shuffle-tests'] or cliArgs.shuffle busted.randomseed = tonumber(cliArgs.seed) or os.time() - if cliArgs.seed ~= defaultSeed and tonumber(cliArgs.seed) == nil then - local err = 'Argument to --seed must be a number' - print('Error: ' .. err) - busted.publish({ 'error' }, {}, nil, err, {}) - end local getFullName = function(name) local parent = busted.context.get() diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 3979247a..ac4a6a82 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -602,12 +602,12 @@ describe('Tests random seed through the commandline', function() error_end() end) - it('test invalid seed value defaults to a valid seed value', function() + it('test invalid seed value exits with error', function() local success, exitcode error_start() success, exitcode = execute(busted_cmd .. ' --seed=abcd --pattern=cl_random_seed.lua$') assert.is_false(success) - assert.is_equal(2, exitcode) -- fails cl_random_seed test +1 error + assert.is_equal(1, exitcode) error_end() end) @@ -663,6 +663,15 @@ describe('Tests repeat commandline option', function() assert.is_equal(4, exitcode) error_end() end) + + it('exits with error when repeat is invalid', function() + local success, exitcode + error_start() + success, exitcode = execute(busted_cmd .. ' --repeat=abc --pattern=cl_success.lua$') + assert.is_false(success) + assert.is_equal(1, exitcode) + error_end() + end) end) describe('Tests no-keep-going commandline option', function() From fd320646a287f724fc9c78426a836701f86b1ebd Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Feb 2015 12:13:26 -0800 Subject: [PATCH 142/293] Refactor output handler / helper script error msg --- busted/runner.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 0ffcf354..a8fb70b4 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -180,12 +180,17 @@ return function(options) local errors = 0 local quitOnError = cliArgs['no-keep-going'] + busted.subscribe({ 'error', 'output' }, function(element, parent, message) + print('Error: Cannot load output library: ' .. element.name .. '\n' .. message) + return nil, true + end) + + busted.subscribe({ 'error', 'helper' }, function(element, parent, message) + print('Error: Cannot load helper script: ' .. element.name .. '\n' .. message) + return nil, true + end) + busted.subscribe({ 'error' }, function(element, parent, message) - if element.descriptor == 'output' then - print('Error: Cannot load output library: ' .. element.name .. '\n' .. message) - elseif element.descriptor == 'helper' then - print('Error: Cannot load helper script: ' .. element.name .. '\n' .. message) - end errors = errors + 1 busted.skipAll = quitOnError return nil, true From 04676aa9fcb6c8104b6620d6176eb6260347796a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Feb 2015 12:42:23 -0800 Subject: [PATCH 143/293] Pull in 'no test files' error message from say --- busted/languages/en.lua | 2 ++ busted/modules/test_file_loader.lua | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/busted/languages/en.lua b/busted/languages/en.lua index aa99b6bd..285d1ba1 100644 --- a/busted/languages/en.lua +++ b/busted/languages/en.lua @@ -25,6 +25,8 @@ s:set('output.success_single', 'success') s:set('output.seconds', 'seconds') +s:set('output.no_test_files_match', 'No test files found matching Lua pattern: %s') + -- definitions following are not used within the 'say' namespace return { failure_messages = { diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 8850e2d5..324c4b49 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -1,3 +1,5 @@ +local s = require 'say' + return function(busted, loaders, options) local path = require 'pl.path' local dir = require 'pl.dir' @@ -71,8 +73,7 @@ return function(busted, loaders, options) end if #fileList == 0 then - local err = 'No test files found matching Lua pattern: ' .. pattern - busted.publish({ 'error' }, {}, nil, err, {}) + busted.publish({ 'error' }, {}, nil, s('output.no_test_files_match'):format(pattern), {}) end return fileList From a197590bf5a255c92f476b9d070f8bfdb1f5d7bb Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Feb 2015 16:38:30 -0800 Subject: [PATCH 144/293] Rename CLI option --no-recurse to --no-recursive --- busted/modules/test_file_loader.lua | 2 +- busted/runner.lua | 4 ++-- completions/bash/busted.bash | 2 +- completions/zsh/_busted | 2 +- spec/cl_spec.lua | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 87eee455..d9e32103 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -16,7 +16,7 @@ return function(busted, loaders, options) if path.isfile(rootFile) then fileList = { rootFile } elseif path.isdir(rootFile) then - local getfiles = options.recurse and dir.getallfiles or dir.getfiles + local getfiles = options.recursive and dir.getallfiles or dir.getfiles fileList = getfiles(rootFile) fileList = tablex.filter(fileList, function(filename) diff --git a/busted/runner.lua b/busted/runner.lua index 398a9293..ba21cd0a 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -81,7 +81,7 @@ return function(options) cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) - cli:add_flag('--no-recurse', 'do not recurse into subdirectories', processOption) + cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) cli:add_flag('--list', 'list the names of all tests instead of running them', processOption) cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) @@ -322,7 +322,7 @@ return function(options) verbose = cliArgs.verbose, sort = cliArgs['sort-files'] or cliArgs.sort, shuffle = cliArgs['shuffle-files'] or cliArgs.shuffle, - recurse = not cliArgs['no-recurse'], + recursive = not cliArgs['no-recursive'], seed = busted.randomseed } diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index c344bf6b..20a7a396 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -138,7 +138,7 @@ _busted() { -Xoutput -Xhelper --no-keep-going - --no-recurse + --no-recursive --shuffle --shuffle-tests --shuffle-files --sort --sort-tests --sort-files --supress-pending diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 8bd00e62..cb0c2b2d 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -20,7 +20,7 @@ _busted_args=( "--version[Prints the program version and exits]" "--list[List the names of all tests instead of running them]" "--no-keep-going[Quit after first error or failure]" -"--no-recurse[Do not recurse into subdirectories]" +"--no-recursive[Do not recurse into subdirectories]" "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" "-Xoutput[Pass 'OPTION' as an option to the output handler. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index d6b9d5bd..fe462d4e 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -676,11 +676,11 @@ describe('Tests no-keep-going commandline option', function() end) end) -describe('Tests no-recurse commandline option', function() +describe('Tests no-recursive commandline option', function() it('does not run any tests in subdirectories', function() local success, exitcode error_start() - success, exitcode = execute(busted_cmd .. ' --no-recurse --pattern=cl_two_failures.lua$ .') + success, exitcode = execute(busted_cmd .. ' --no-recursive --pattern=cl_two_failures.lua$ .') assert.is_false(success) assert.is_equal(1, exitcode) error_end() From aa7f3d9dd1976e59a0fbc056c398e29ce10bf1e6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Feb 2015 16:39:03 -0800 Subject: [PATCH 145/293] Add -l command-line option as alias to --list --- busted/runner.lua | 2 +- completions/bash/busted.bash | 2 +- completions/zsh/_busted | 2 +- spec/cl_spec.lua | 8 ++++++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index ba21cd0a..71a991cf 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -80,9 +80,9 @@ return function(options) cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', processOption) cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) + cli:add_flag('-l, --list', 'list the names of all tests instead of running them', processOption) cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) - cli:add_flag('--list', 'list the names of all tests instead of running them', processOption) cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 20a7a396..bbab5db0 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -120,7 +120,7 @@ _busted() { -h --help -v --verbose --version - --list + -l --list -o --output= -p --pattern= -d --cwd= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index cb0c2b2d..37c33233 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -18,7 +18,7 @@ _busted_args=( "(--sort-tests --shuffle-tests)--sort-tests[Sort test order within a file]" "--suppress-pending[Suppress 'pending' test output]" "--version[Prints the program version and exits]" -"--list[List the names of all tests instead of running them]" +"(-l --list)"{-l,--list}"[List the names of all tests instead of running them]" "--no-keep-going[Quit after first error or failure]" "--no-recursive[Do not recurse into subdirectories]" "--helper[A helper script that is run before tests]:files:_files" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index fe462d4e..e1acc328 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -159,6 +159,14 @@ describe('Tests the busted command-line options', function() error_end() end) + it('tests running with -l specified', function() + local result = run(busted_cmd .. ' -l --pattern=cl_list.lua$') + local expected = './spec/cl_list.lua:4: Tests list test 1\n' .. + './spec/cl_list.lua:7: Tests list test 2\n' .. + './spec/cl_list.lua:10: Tests list test 3\n' + assert.is_equal(normpath(expected), result) + end) + it('tests running with --list specified', function() local result = run(busted_cmd .. ' --list --pattern=cl_list.lua$') local expected = './spec/cl_list.lua:4: Tests list test 1\n' .. From 96c72fbbef8a276003f4c3fad3448eabf60d5143 Mon Sep 17 00:00:00 2001 From: iggyvolz Date: Wed, 25 Feb 2015 17:30:38 -0500 Subject: [PATCH 146/293] Add French translation for error handling --- busted/languages/fr.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/busted/languages/fr.lua b/busted/languages/fr.lua index 78a05ae5..236d87c8 100644 --- a/busted/languages/fr.lua +++ b/busted/languages/fr.lua @@ -21,6 +21,8 @@ s:set('output.success_single', 'reussite') s:set('output.seconds', 'secondes') +s:set('output.no_test_files_match', 'Aucun test n\'est pourrait trouvé qui corresponde au motif de Lua: %s') + -- definitions following are not used within the 'say' namespace return { failure_messages = { From 0f1090710b99f482313d8cf1124a9672e77b3b2f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 26 Feb 2015 12:24:15 -0800 Subject: [PATCH 147/293] Check for possible nil command-line options --- busted/runner.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 51a32877..91ce94e5 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -212,7 +212,7 @@ return function(options) suppressPending = cliArgs['suppress-pending'], language = cliArgs.lang, deferPrint = cliArgs['defer-print'], - arguments = utils.split(cliArgs.Xoutput, ',') or {} + arguments = utils.split(cliArgs.Xoutput or '', ',') or {} } local opath = utils.normpath(path.join(fpath, cliArgs.output)) @@ -318,11 +318,11 @@ return function(options) applyFilter({ 'describe', 'it', 'pending' }, 'exclude-tags', filterExcludeTags) -- Set up helper script - if cliArgs.helper ~= '' then + if cliArgs.helper and cliArgs.helper ~= '' then local helperOptions = { verbose = cliArgs.verbose, language = cliArgs.lang, - arguments = utils.split(cliArgs.Xhelper, ',') or {} + arguments = utils.split(cliArgs.Xhelper or '', ',') or {} } local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) From 04844d07e2487682f7fa634aba19536bd3100d33 Mon Sep 17 00:00:00 2001 From: Robert Ditthardt Date: Fri, 27 Feb 2015 11:58:40 -0800 Subject: [PATCH 148/293] Version 2.0.rc7-0 --- busted-2.0.rc6-0.rockspec => busted-2.0.rc7-0.rockspec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename busted-2.0.rc6-0.rockspec => busted-2.0.rc7-0.rockspec (96%) diff --git a/busted-2.0.rc6-0.rockspec b/busted-2.0.rc7-0.rockspec similarity index 96% rename from busted-2.0.rc6-0.rockspec rename to busted-2.0.rc7-0.rockspec index ea8ae610..ed00171b 100644 --- a/busted-2.0.rc6-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc6-0' +version = '2.0.rc7-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc6.tar.gz', - dir = 'busted-2.0.rc6' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc7-0.tar.gz', + dir = 'busted-2.0.rc7-0' } description = { summary = 'Elegant Lua unit testing.', @@ -22,7 +22,7 @@ dependencies = { 'lua_cliargs >= 2.3-3', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', - 'say >= 1.2-1', + 'say >= 1.3-0', 'luassert >= 1.7.4-0', 'ansicolors >= 1.0-1', 'lua-term >= 0.1-1', From 72d8d1055d37e5e98054ab49e9f2ae5a0fe80548 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Sat, 28 Feb 2015 10:35:37 -0800 Subject: [PATCH 149/293] keep scm rockspec updated, use in helper scripts --- busted-scm-0.rockspec | 2 +- try | 2 +- try.bat | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 4ee5cb25..4369eecc 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -22,7 +22,7 @@ dependencies = { 'lua_cliargs >= 2.3-3', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', - 'say >= 1.2-1', + 'say >= 1.3-0', 'luassert >= 1.7.4-0', 'ansicolors >= 1.0-1', 'lua-term >= 0.1-1', diff --git a/try b/try index f697bf5b..fe04aa13 100755 --- a/try +++ b/try @@ -1,4 +1,4 @@ #!/bin/sh sudo luarocks remove busted --force -sudo luarocks make +sudo luarocks make busted-scm-0.rockspec busted diff --git a/try.bat b/try.bat index 89510472..0d4dba36 100644 --- a/try.bat +++ b/try.bat @@ -1,4 +1,4 @@ call luarocks remove busted --force -call luarocks make +call luarocks make busted-scm-0.rockspec cls call busted From f2e45ad7f16f7f8c544dfdf073cc161a32b7b405 Mon Sep 17 00:00:00 2001 From: mpeterv Date: Fri, 6 Mar 2015 16:40:57 +0300 Subject: [PATCH 150/293] Replace ansicolors with lua-term Since lua-term is already used and has a submodule equivalent to ansicolors, use lua-term for color handling. --- busted-scm-0.rockspec | 1 - busted/outputHandlers/utfTerminal.lua | 42 +++++++++++++-------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 4369eecc..806105c3 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -24,7 +24,6 @@ dependencies = { 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.4-0', - 'ansicolors >= 1.0-1', 'lua-term >= 0.1-1', 'penlight >= 1.0.0-1', 'mediator_lua >= 1.1-3', diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index f34015cc..9aa8e714 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -1,22 +1,22 @@ -local ansicolors = require 'ansicolors' +local colors = require 'term.colors' local s = require 'say' local pretty = require 'pl.pretty' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) - local successDot = ansicolors('%{green}●') - local failureDot = ansicolors('%{red}◼') - local errorDot = ansicolors('%{magenta}✱') - local pendingDot = ansicolors('%{yellow}◌') + local successDot = colors.green('●') + local failureDot = colors.red('◼') + local errorDot = colors.magenta('✱') + local pendingDot = colors.yellow('◌') local pendingDescription = function(pending) local name = pending.name - local string = ansicolors('%{yellow}' .. s('output.pending')) .. ' → ' .. - ansicolors('%{cyan}' .. pending.trace.short_src) .. ' @ ' .. - ansicolors('%{cyan}' .. pending.trace.currentline) .. - '\n' .. ansicolors('%{bright}' .. name) + local string = colors.yellow(s('output.pending')) .. ' → ' .. + colors.cyan(pending.trace.short_src) .. ' @ ' .. + colors.cyan(pending.trace.currentline) .. + '\n' .. colors.bright(name) if type(pending.message) == 'string' then string = string .. '\n' .. pending.message @@ -41,20 +41,20 @@ return function(options, busted) end local failureDescription = function(failure, isError) - local string = ansicolors('%{red}' .. s('output.failure')) .. ' → ' + local string = colors.red(s('output.failure')) .. ' → ' if isError then - string = ansicolors('%{magenta}' .. s('output.error')) .. ' → ' + string = colors.magenta(s('output.error')) .. ' → ' end if not failure.element.trace or not failure.element.trace.short_src then string = string .. - ansicolors('%{cyan}' .. failureMessage(failure)) .. '\n' .. - ansicolors('%{bright}' .. failure.name) + colors.cyan(failureMessage(failure)) .. '\n' .. + colors.bright(failure.name) else string = string .. - ansicolors('%{cyan}' .. failure.element.trace.short_src) .. ' @ ' .. - ansicolors('%{cyan}' .. failure.element.trace.currentline) .. '\n' .. - ansicolors('%{bright}' .. failure.name) .. '\n' .. + colors.cyan(failure.element.trace.short_src) .. ' @ ' .. + colors.cyan(failure.element.trace.currentline) .. '\n' .. + colors.bright(failure.name) .. '\n' .. failureMessage(failure) end @@ -103,11 +103,11 @@ return function(options, busted) local formattedTime = ('%.6f'):format(ms):gsub('([0-9])0+$', '%1') - return ansicolors('%{green}' .. successes) .. ' ' .. successString .. ' / ' .. - ansicolors('%{red}' .. failures) .. ' ' .. failureString .. ' / ' .. - ansicolors('%{magenta}' .. errors) .. ' ' .. errorString .. ' / ' .. - ansicolors('%{yellow}' .. pendings) .. ' ' .. pendingString .. ' : ' .. - ansicolors('%{bright}' .. formattedTime) .. ' ' .. s('output.seconds') + return colors.green(successes) .. ' ' .. successString .. ' / ' .. + colors.red(failures) .. ' ' .. failureString .. ' / ' .. + colors.magenta(errors) .. ' ' .. errorString .. ' / ' .. + colors.yellow(pendings) .. ' ' .. pendingString .. ' : ' .. + colors.bright(formattedTime) .. ' ' .. s('output.seconds') end handler.testEnd = function(element, parent, status, debug) From a6e1edb3f37d086dcea5e6026e00120c090f400d Mon Sep 17 00:00:00 2001 From: mpeterv Date: Fri, 6 Mar 2015 17:27:41 +0300 Subject: [PATCH 151/293] Fix passing arguments to helpers Do not pass array containing an empty string as cli args for helpers when they are not specified. --- busted/runner.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 91ce94e5..5f3d5ad5 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -212,7 +212,7 @@ return function(options) suppressPending = cliArgs['suppress-pending'], language = cliArgs.lang, deferPrint = cliArgs['defer-print'], - arguments = utils.split(cliArgs.Xoutput or '', ',') or {} + arguments = cliArgs.Xoutput and utils.split(cliArgs.Xoutput, ',') or {} } local opath = utils.normpath(path.join(fpath, cliArgs.output)) @@ -322,7 +322,7 @@ return function(options) local helperOptions = { verbose = cliArgs.verbose, language = cliArgs.lang, - arguments = utils.split(cliArgs.Xhelper or '', ',') or {} + arguments = cliArgs.Xhelper and utils.split(cliArgs.Xhelper, ',') or {} } local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) From bf721665f8aa1bb7309b7f2d8ffcd3d8f88b5b2b Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 5 Mar 2015 01:07:48 -0800 Subject: [PATCH 152/293] Fix getfenv --- busted/compatibility.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 7837656f..e7654fb4 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -9,7 +9,7 @@ return { name, value = debug.getupvalue(f, up) until name == '_ENV' or name == nil - return value + return name and value or _G end, setfenv = setfenv or function(f, t) From 1a8c61d77ef3d261cc3e529b75ab35cf3117b948 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 19 Feb 2015 17:20:00 -0800 Subject: [PATCH 153/293] Refactor context block execution Eliminate duplicate code in file and describe blocks. --- busted-2.0.rc7-0.rockspec | 1 + busted-scm-0.rockspec | 1 + busted/block.lua | 37 ++++++++++ busted/core.lua | 75 ++++++++++++++++++++ busted/init.lua | 141 +++----------------------------------- 5 files changed, 123 insertions(+), 132 deletions(-) create mode 100644 busted/block.lua diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index ed00171b..6dffd190 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -40,6 +40,7 @@ build = { ['busted.runner'] = 'busted/runner.lua', ['busted.status'] = 'busted/status.lua', ['busted.utils'] = 'busted/utils.lua', + ['busted.block'] = 'busted/block.lua', ['busted.init'] = 'busted/init.lua', ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 806105c3..b60dbb15 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -39,6 +39,7 @@ build = { ['busted.runner'] = 'busted/runner.lua', ['busted.status'] = 'busted/status.lua', ['busted.utils'] = 'busted/utils.lua', + ['busted.block'] = 'busted/block.lua', ['busted.init'] = 'busted/init.lua', ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', diff --git a/busted/block.lua b/busted/block.lua new file mode 100644 index 00000000..cc23e546 --- /dev/null +++ b/busted/block.lua @@ -0,0 +1,37 @@ +local shuffle = require 'busted.utils'.shuffle + +local function sort(elements) + table.sort(elements, function(t1, t2) + if t1.name and t2.name then + return t1.name < t2.name + end + return t2.name ~= nil + end) + return elements +end + +return function(busted) + local block = {} + + function block.execute(descriptor, element) + if not element.env then element.env = {} end + + local randomize = busted.randomize + element.env.randomize = function() randomize = true end + + if busted.safe(descriptor, element.run, element):success() then + if randomize then + element.randomseed = busted.randomseed + shuffle(busted.context.children(element), busted.randomseed) + elseif busted.sort then + sort(busted.context.children(element)) + end + if busted.execAll('setup', element) then + busted.execute(element) + end + busted.dexecAll('teardown', element) + end + end + + return block +end diff --git a/busted/core.lua b/busted/core.lua index 802e60c8..1451b957 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -223,6 +223,81 @@ return function() environment.set(alias, publisher) end + function busted.reject(descriptor, element) + local env = getfenv(element.run) + if env[descriptor] then + element.env[descriptor] = function(...) + error("'" .. descriptor .. "' not supported inside current context block", 2) + end + end + end + + function busted.rejectAll(element) + busted.reject('randomize', element) + for descriptor, _ in pairs(busted.executors) do + busted.reject(descriptor, element) + end + end + + local function exec(descriptor, element) + if not element.env then element.env = {} end + + busted.rejectAll(element) + + local parent = busted.context.parent(element) + setmetatable(element.env, { + __newindex = function(self, key, value) + if not parent.env then parent.env = {} end + parent.env[key] = value + end + }) + + local ret = { busted.safe(descriptor, element.run, element) } + return unpack(ret) + end + + function busted.execAll(descriptor, current, propagate, err) + local parent = busted.context.parent(current) + + if propagate and parent then + local success, ancestor = busted.execAll(descriptor, parent, propagate) + if not success then + return success, ancestor + end + end + + local list = current[descriptor] or {} + + local success = true + for _, v in pairs(list) do + if not exec(descriptor, v):success() then + if err then err(descriptor) end + success = nil + end + end + return success, current + end + + function busted.dexecAll(descriptor, current, propagate, err) + local parent = busted.context.parent(current) + local list = current[descriptor] or {} + + local success = true + for _, v in pairs(list) do + if not exec(descriptor, v):success() then + if err then err(descriptor) end + success = nil + end + end + + if propagate and parent then + if not busted.dexecAll(descriptor, parent, propagate) then + success = nil + end + end + return success + end + function busted.execute(current) if not current then current = busted.context.get() end for _, v in pairs(busted.context.children(current)) do diff --git a/busted/init.lua b/busted/init.lua index da052f50..065f1956 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -1,133 +1,17 @@ -local unpack = require 'busted.compatibility'.unpack -local shuffle = require 'busted.utils'.shuffle - -local function sort(elements) - table.sort(elements, function(t1, t2) - if t1.name and t2.name then - return t1.name < t2.name - end - return t2.name ~= nil - end) - return elements -end - -local function remove(descriptors, element) - for _, descriptor in ipairs(descriptors) do - element.env[descriptor] = function(...) - error("'" .. descriptor .. "' not supported inside current context block", 2) - end - end -end - local function init(busted) - local function exec(descriptor, element) - if not element.env then element.env = {} end - - remove({ 'randomize' }, element) - remove({ 'pending' }, element) - remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) - remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) - - local parent = busted.context.parent(element) - setmetatable(element.env, { - __newindex = function(self, key, value) - if not parent.env then parent.env = {} end - parent.env[key] = value - end - }) - - local ret = { busted.safe(descriptor, element.run, element) } - return unpack(ret) - end - - local function execAll(descriptor, current, propagate) - local parent = busted.context.parent(current) - - if propagate and parent then - local success, ancestor = execAll(descriptor, parent, propagate) - if not success then - return success, ancestor - end - end - - local list = current[descriptor] or {} - - local success = true - for _, v in pairs(list) do - if not exec(descriptor, v):success() then - success = nil - end - end - return success, current - end - - local function dexecAll(descriptor, current, propagate) - local parent = busted.context.parent(current) - local list = current[descriptor] or {} - - local success = true - for _, v in pairs(list) do - if not exec(descriptor, v):success() then - success = nil - end - end - - if propagate and parent then - if not dexecAll(descriptor, parent, propagate) then - success = nil - end - end - return success - end + local block = require 'busted.block'(busted) local file = function(file) - busted.publish({ 'file', 'start' }, file.name) - busted.environment.wrap(file.run) - if not file.env then file.env = {} end - - local randomize = busted.randomize - file.env.randomize = function() randomize = true end - - if busted.safe('file', file.run, file):success() then - if randomize then - file.randomseed = busted.randomseed - shuffle(busted.context.children(file), busted.randomseed) - elseif busted.sort then - sort(busted.context.children(file)) - end - if execAll('setup', file) then - busted.execute(file) - end - dexecAll('teardown', file) - end - + busted.publish({ 'file', 'start' }, file.name) + block.execute('file', file) busted.publish({ 'file', 'end' }, file.name) end local describe = function(describe) local parent = busted.context.parent(describe) - busted.publish({ 'describe', 'start' }, describe, parent) - - if not describe.env then describe.env = {} end - - local randomize = busted.randomize - describe.env.randomize = function() randomize = true end - - if busted.safe('describe', describe.run, describe):success() then - if randomize then - describe.randomseed = busted.randomseed - shuffle(busted.context.children(describe), busted.randomseed) - elseif busted.sort then - sort(busted.context.children(describe)) - end - if execAll('setup', describe) then - busted.execute(describe) - end - dexecAll('teardown', describe) - end - + block.execute('describe', describe) busted.publish({ 'describe', 'end' }, describe, parent) end @@ -139,33 +23,26 @@ local function init(busted) if not element.env then element.env = {} end - remove({ 'randomize' }, element) - remove({ 'describe', 'context', 'it', 'spec', 'test' }, element) - remove({ 'setup', 'teardown', 'before_each', 'after_each' }, element) + busted.rejectAll(element) element.env.finally = function(fn) finally = fn end element.env.pending = function(msg) busted.pending(msg) end local status = busted.status('success') - local updateErrorStatus = function(descriptor) + local onError = function(descriptor) if element.message then element.message = element.message .. '\n' end element.message = (element.message or '') .. 'Error in ' .. descriptor status:update('error') end - local pass, ancestor = execAll('before_each', parent, true) + local pass, ancestor = busted.execAll('before_each', parent, true, onError) if pass then status:update(busted.safe('it', element.run, element)) - else - updateErrorStatus('before_each') end if not element.env.done then - remove({ 'pending' }, element) + busted.reject('pending', element) if finally then status:update(busted.safe('finally', finally, element)) end - if not dexecAll('after_each', ancestor, true) then - updateErrorStatus('after_each') - end - + busted.dexecAll('after_each', ancestor, true, onError) busted.publish({ 'test', 'end' }, element, parent, tostring(status)) end end From b2be075fa75c225e724f9d8dd4765ba3f335c858 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 20 Feb 2015 11:38:50 -0800 Subject: [PATCH 154/293] Remove check for `done` variable at test end The `done` variable is not used anywhere and async tests are not supported yet, so remove this unnecessary check. --- busted/init.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 065f1956..7cd1fcb2 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -39,12 +39,13 @@ local function init(busted) status:update(busted.safe('it', element.run, element)) end - if not element.env.done then + if finally then busted.reject('pending', element) - if finally then status:update(busted.safe('finally', finally, element)) end - busted.dexecAll('after_each', ancestor, true, onError) - busted.publish({ 'test', 'end' }, element, parent, tostring(status)) + status:update(busted.safe('finally', finally, element)) end + busted.dexecAll('after_each', ancestor, true, onError) + + busted.publish({ 'test', 'end' }, element, parent, tostring(status)) end local pending = function(element) From 0b95c5232edbb01c5bb0f0d305c790a34e1c0474 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 09:38:12 -0800 Subject: [PATCH 155/293] Do not execute finally block if test not executed --- busted/init.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 7cd1fcb2..8a8d87db 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -37,11 +37,10 @@ local function init(busted) local pass, ancestor = busted.execAll('before_each', parent, true, onError) if pass then status:update(busted.safe('it', element.run, element)) - end - - if finally then - busted.reject('pending', element) - status:update(busted.safe('finally', finally, element)) + if finally then + busted.reject('pending', element) + status:update(busted.safe('finally', finally, element)) + end end busted.dexecAll('after_each', ancestor, true, onError) From 0359b314e4a061ce4e73e442673eb2d05d027a52 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 10:47:52 -0800 Subject: [PATCH 156/293] Only publish test start/end if before_each passes --- busted/init.lua | 16 +++++----------- spec/cl_failing_support.lua | 3 +++ spec/cl_spec.lua | 4 ++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index 8a8d87db..c51bd5e9 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -19,32 +19,26 @@ local function init(busted) local parent = busted.context.parent(element) local finally - busted.publish({ 'test', 'start' }, element, parent) - if not element.env then element.env = {} end busted.rejectAll(element) element.env.finally = function(fn) finally = fn end element.env.pending = function(msg) busted.pending(msg) end - local status = busted.status('success') - local onError = function(descriptor) - if element.message then element.message = element.message .. '\n' end - element.message = (element.message or '') .. 'Error in ' .. descriptor - status:update('error') - end + local pass, ancestor = busted.execAll('before_each', parent, true) - local pass, ancestor = busted.execAll('before_each', parent, true, onError) if pass then + local status = busted.status('success') + busted.publish({ 'test', 'start' }, element, parent) status:update(busted.safe('it', element.run, element)) if finally then busted.reject('pending', element) status:update(busted.safe('finally', finally, element)) end + busted.publish({ 'test', 'end' }, element, parent, tostring(status)) end - busted.dexecAll('after_each', ancestor, true, onError) - busted.publish({ 'test', 'end' }, element, parent, tostring(status)) + busted.dexecAll('after_each', ancestor, true) end local pending = function(element) diff --git a/spec/cl_failing_support.lua b/spec/cl_failing_support.lua index 44942075..86da16c2 100644 --- a/spec/cl_failing_support.lua +++ b/spec/cl_failing_support.lua @@ -29,6 +29,9 @@ describe('bad support functions should fail, sync test', function() it('Tests nothing, should always fail due to failing support functions', function() end) + + it('Tests nothing, should always fail due to failing support functions', function() + end) end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index b1f6d736..190786b0 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -264,7 +264,7 @@ describe('Tests failing tests through the commandline', function() error_start() success, exitcode = execute(busted_cmd .. ' --pattern=cl_failing_support.lua$') assert.is_false(success) - assert.is_equal(8, exitcode) + assert.is_equal(9, exitcode) error_end() end) @@ -272,7 +272,7 @@ describe('Tests failing tests through the commandline', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_failing_support.lua$') local _, numErrors = result:gsub('Error → .-\n','') - assert.is_equal(12, numErrors) + assert.is_equal(9, numErrors) error_end() end) end) From 63bdb0f8353bc8f30d364ab92b702c4fc1d2cd5c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 10:55:58 -0800 Subject: [PATCH 157/293] Do not export file executor to external modules --- busted/init.lua | 2 +- spec/executors_spec.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/busted/init.lua b/busted/init.lua index c51bd5e9..d9e1e518 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -87,7 +87,7 @@ return setmetatable({}, { return setmetatable(self, { __index = function(self, key) - return rawget(root.env, key) or busted.executors[key] + return rawget(root.env, key) end, __newindex = function(self, key, value) diff --git a/spec/executors_spec.lua b/spec/executors_spec.lua index 59b302be..a263348b 100644 --- a/spec/executors_spec.lua +++ b/spec/executors_spec.lua @@ -15,8 +15,8 @@ describe('tests require "busted"', function() assert.is_nil(require 'busted'.init) end) - it('imports file executor', function() - assert.is_function(require 'busted'.file) + it('does not import file executor', function() + assert.is_nil(require 'busted'.file) end) it('imports describe/it/pending', function() From 64519a230d335133bb1943dac00d91bc4c53ca5f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 3 Mar 2015 12:28:00 -0800 Subject: [PATCH 158/293] Export publish/subscribe to external modules --- busted/core.lua | 35 +++++++++++++------- busted/init.lua | 19 ++++++----- spec/{executors_spec.lua => export_spec.lua} | 25 ++++++++++---- 3 files changed, 53 insertions(+), 26 deletions(-) rename spec/{executors_spec.lua => export_spec.lua} (66%) diff --git a/busted/core.lua b/busted/core.lua index 1451b957..3c3545c3 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -41,17 +41,8 @@ return function() busted.context = root.ref() local environment = require 'busted.environment'(busted.context) - busted.environment = { - set = environment.set, - - wrap = function(callable) - if (type(callable) == 'function' or getmetatable(callable).__call) then - -- prioritize __call if it exists, like in files - environment.wrap((getmetatable(callable) or {}).__call or callable) - end - end - } + busted.modules = {} busted.executors = {} local executors = {} @@ -99,6 +90,10 @@ return function() return mediator:subscribe(...) end + function busted.unsubscribe(...) + return mediator:removeSubscriber(...) + end + function busted.getFile(element) local parent = busted.context.parent(element) @@ -149,6 +144,13 @@ return function() setfenv(f, env) end + function busted.wrap(callable) + if (type(callable) == 'function' or getmetatable(callable).__call) then + -- prioritize __call if it exists, like in files + environment.wrap((getmetatable(callable) or {}).__call or callable) + end + end + function busted.safe(descriptor, run, element) busted.context.push(element) local trace, message @@ -170,6 +172,15 @@ return function() return unpack(ret) end + function busted.exportApi(key, value) + busted.modules[key] = value + end + + function busted.export(key, value) + busted.exportApi(key, value) + environment.set(key, value) + end + function busted.register(descriptor, executor) executors[descriptor] = executor @@ -195,7 +206,7 @@ return function() busted.executors[descriptor] = publisher if descriptor ~= 'file' then - environment.set(descriptor, publisher) + busted.export(descriptor, publisher) end busted.subscribe({ 'register', descriptor }, function(name, fn, trace) @@ -220,7 +231,7 @@ return function() function busted.alias(alias, descriptor) local publisher = busted.executors[descriptor] busted.executors[alias] = publisher - environment.set(alias, publisher) + busted.export(alias, publisher) end function busted.reject(descriptor, element) diff --git a/busted/init.lua b/busted/init.lua index d9e1e518..90ad16af 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -2,7 +2,7 @@ local function init(busted) local block = require 'busted.block'(busted) local file = function(file) - busted.environment.wrap(file.run) + busted.wrap(file.run) busted.publish({ 'file', 'start' }, file.name) block.execute('file', file) busted.publish({ 'file', 'end' }, file.name) @@ -69,25 +69,28 @@ local function init(busted) local mock = require 'luassert.mock' local stub = require 'luassert.stub' - busted.environment.set('assert', assert) - busted.environment.set('spy', spy) - busted.environment.set('mock', mock) - busted.environment.set('stub', stub) + busted.export('assert', assert) + busted.export('spy', spy) + busted.export('mock', mock) + busted.export('stub', stub) + + busted.exportApi('publish', busted.publish) + busted.exportApi('subscribe', busted.subscribe) + busted.exportApi('unsubscribe', busted.unsubscribe) busted.replaceErrorWithFail(assert) - busted.replaceErrorWithFail(assert.True) + busted.replaceErrorWithFail(assert.is_true) return busted end return setmetatable({}, { __call = function(self, busted) - local root = busted.context.get() init(busted) return setmetatable(self, { __index = function(self, key) - return rawget(root.env, key) + return busted.modules[key] end, __newindex = function(self, key, value) diff --git a/spec/executors_spec.lua b/spec/export_spec.lua similarity index 66% rename from spec/executors_spec.lua rename to spec/export_spec.lua index a263348b..efb83b3e 100644 --- a/spec/executors_spec.lua +++ b/spec/export_spec.lua @@ -11,40 +11,53 @@ describe('tests require "busted"', function() local before_each = before_each local after_each = after_each - it('does not import init', function() + it('does not export init', function() assert.is_nil(require 'busted'.init) end) - it('does not import file executor', function() + it('does not export file executor', function() assert.is_nil(require 'busted'.file) end) - it('imports describe/it/pending', function() + it('exports describe/it/pending', function() assert.is_equal(describe, require 'busted'.describe) assert.is_equal(it, require 'busted'.it) assert.is_equal(pending, require 'busted'.pending) end) - it('imports aliases', function() + it('exports aliases', function() assert.is_equal(context, require 'busted'.context) assert.is_equal(spec, require 'busted'.spec) assert.is_equal(test, require 'busted'.test) end) - it('imports support functions', function() + it('exports support functions', function() assert.is_equal(setup, require 'busted'.setup) assert.is_equal(teardown, require 'busted'.teardown) assert.is_equal(before_each, require 'busted'.before_each) assert.is_equal(after_each, require 'busted'.after_each) end) - it('imports assert and mocks', function() + it('exports assert and mocks', function() assert.is_equal(assert, require 'busted'.assert) assert.is_equal(spy, require 'busted'.spy) assert.is_equal(mock, require 'busted'.mock) assert.is_equal(stub, require 'busted'.stub) end) + it('exports publish/subscribe', function() + local foo + local publish = require 'busted'.publish + local subscribe = require 'busted'.subscribe + local unsubscribe = require 'busted'.unsubscribe + local sub = subscribe({'export_test'}, function(...) foo = {...} end) + publish({'export_test'}, 'value1', 'value2' ) + local unsub = unsubscribe(sub.id, {'export_test'}) + publish({'export_test'}, 'new_value1', 'new_value2') + assert.is_same({'value1', 'value2'}, foo) + assert.is_equal(sub, unsub) + end) + it('functions cannot be overwritten', function() local foo = function() assert(false) end assert.has_error(function() require 'busted'.it = foo end) From 3b304ddd53845adf05e2984031b6ff0274c274f3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 12:01:55 -0800 Subject: [PATCH 159/293] Refactor test suite execution into separate file --- busted-2.0.rc7-0.rockspec | 1 + busted-scm-0.rockspec | 1 + busted/execute.lua | 42 +++++++++++++++++++++++++++++++++++++++ busted/runner.lua | 37 ++-------------------------------- 4 files changed, 46 insertions(+), 35 deletions(-) create mode 100644 busted/execute.lua diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index 6dffd190..e825c4c6 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -41,6 +41,7 @@ build = { ['busted.status'] = 'busted/status.lua', ['busted.utils'] = 'busted/utils.lua', ['busted.block'] = 'busted/block.lua', + ['busted.execute'] = 'busted/execute.lua', ['busted.init'] = 'busted/init.lua', ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index b60dbb15..94aca3b2 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -40,6 +40,7 @@ build = { ['busted.status'] = 'busted/status.lua', ['busted.utils'] = 'busted/utils.lua', ['busted.block'] = 'busted/block.lua', + ['busted.execute'] = 'busted/execute.lua', ['busted.init'] = 'busted/init.lua', ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', diff --git a/busted/execute.lua b/busted/execute.lua new file mode 100644 index 00000000..3825da00 --- /dev/null +++ b/busted/execute.lua @@ -0,0 +1,42 @@ + +return function(busted) + local function execute(runs, options) + busted.subscribe({'suite', 'reinitialize'}, function() + local oldctx = busted.context.get() + local children = busted.context.children(oldctx) + + busted.context.clear() + local ctx = busted.context.get() + for k, v in pairs(oldctx) do + ctx[k] = v + end + + for _, child in pairs(children) do + for descriptor, _ in pairs(busted.executors) do + child[descriptor] = nil + end + busted.context.attach(child) + end + + busted.randomseed = tonumber(options.seed) or os.time() + + return nil, true + end) + + for i = 1, runs do + if i > 1 then + busted.publish({ 'suite', 'reinitialize' }) + end + + busted.publish({ 'suite', 'start' }, i, runs) + busted.execute() + busted.publish({ 'suite', 'end' }, i, runs) + + if busted.skipAll then + break + end + end + end + + return execute +end diff --git a/busted/runner.lua b/busted/runner.lua index 5f3d5ad5..f9f331c1 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -350,42 +350,9 @@ return function(options) getmetatable(file.run).__call = info.func end - busted.subscribe({'suite', 'reinitialize'}, function() - local oldctx = busted.context.get() - local children = busted.context.children(oldctx) - - busted.context.clear() - local ctx = busted.context.get() - for k, v in pairs(oldctx) do - ctx[k] = v - end - - for _, child in pairs(children) do - for descriptor, _ in pairs(busted.executors) do - child[descriptor] = nil - end - busted.context.attach(child) - end - - busted.randomseed = tonumber(cliArgs.seed) or os.time() - - return nil, true - end) - local runs = tonumber(cliArgs['repeat']) or 1 - for i = 1, runs do - if i > 1 then - busted.publish({ 'suite', 'reinitialize' }) - end - - busted.publish({ 'suite', 'start' }, i, runs) - busted.execute() - busted.publish({ 'suite', 'end' }, i, runs) - - if quitOnError and (failures > 0 or errors > 0) then - break - end - end + local execute = require 'busted.execute'(busted) + execute(runs, { seed = cliArgs.seed }) busted.publish({ 'exit' }) From 64a378915572a0c7e059f7f18f9085fc3ca8984c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 12:05:01 -0800 Subject: [PATCH 160/293] Execute setup/teardown for test suite --- busted/execute.lua | 6 +++++- spec/cl_helper_script.lua | 12 ++++++++++++ spec/cl_spec.lua | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/busted/execute.lua b/busted/execute.lua index 3825da00..7670945c 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -28,8 +28,12 @@ return function(busted) busted.publish({ 'suite', 'reinitialize' }) end + local root = busted.context.get() busted.publish({ 'suite', 'start' }, i, runs) - busted.execute() + if busted.execAll('setup', root) then + busted.execute() + end + busted.dexecAll('teardown', root) busted.publish({ 'suite', 'end' }, i, runs) if busted.skipAll then diff --git a/spec/cl_helper_script.lua b/spec/cl_helper_script.lua index 0f91e536..c8db6f87 100644 --- a/spec/cl_helper_script.lua +++ b/spec/cl_helper_script.lua @@ -1,16 +1,28 @@ -- supporting testfile; belongs to 'cl_spec.lua' +local setup = require 'busted'.setup +local teardown = require 'busted'.teardown local before_each = require 'busted'.before_each local after_each = require 'busted'.after_each local assert = require 'busted'.assert local cli = require 'cliargs' cli:set_name('cl_helper_script') +cli:add_flag('--fail-setup', 'force setup to fail') +cli:add_flag('--fail-teardown', 'force teardown to fail') cli:add_flag('--fail-before-each', 'force before each to fail') cli:add_flag('--fail-after-each', 'force after each to fail') local cliArgs = cli:parse(arg) +setup(function() + assert(not cliArgs['fail-setup']) +end) + +teardown(function() + assert(not cliArgs['fail-teardown']) +end) + before_each(function() assert(not cliArgs['fail-before-each']) end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 190786b0..d4ccbbc6 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -742,3 +742,17 @@ describe('Tests Xhelper commandline option', function() assert.is_equal(2, exitcode) end) end) + +describe('Tests helper script', function() + it('can add setup to test suite', function() + local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup" --pattern=cl_two_failures.lua$') + assert.is_false(success) + assert.is_equal(1, exitcode) + end) + + it('can add teardown to test suite', function() + local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown" --pattern=cl_two_failures.lua$') + assert.is_false(success) + assert.is_equal(3, exitcode) + end) +end) From 03fffcdf005b1b4f051cae16e46f386499dee135 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 24 Feb 2015 17:15:04 -0800 Subject: [PATCH 161/293] Rename refactor suite reinitialize to suite reset --- busted/execute.lua | 4 ++-- busted/outputHandlers/base.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/busted/execute.lua b/busted/execute.lua index 7670945c..dfa5c9fe 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -1,7 +1,7 @@ return function(busted) local function execute(runs, options) - busted.subscribe({'suite', 'reinitialize'}, function() + busted.subscribe({'suite', 'reset'}, function() local oldctx = busted.context.get() local children = busted.context.children(oldctx) @@ -25,7 +25,7 @@ return function(busted) for i = 1, runs do if i > 1 then - busted.publish({ 'suite', 'reinitialize' }) + busted.publish({ 'suite', 'reset' }) end local root = busted.context.get() diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 5ea9540f..5043c0a2 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -23,7 +23,7 @@ return function(busted) require('busted.languages.' .. options.language) end - busted.subscribe({ 'suite', 'reinitialize' }, handler.baseSuiteRepeat, { priority = 1 }) + busted.subscribe({ 'suite', 'reset' }, handler.baseSuiteReset, { priority = 1 }) busted.subscribe({ 'suite', 'start' }, handler.baseSuiteStart, { priority = 1 }) busted.subscribe({ 'suite', 'end' }, handler.baseSuiteEnd, { priority = 1 }) busted.subscribe({ 'test', 'start' }, handler.baseTestStart, { priority = 1, predicate = handler.cancelOnPending }) @@ -75,7 +75,7 @@ return function(busted) return nil, true end - handler.baseSuiteRepeat = function() + handler.baseSuiteReset = function() handler.successes = {} handler.successesCount = 0 handler.pendings = {} From 6399a6f79d3b9d3541534bab33e03ff2ad4f59e3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Feb 2015 12:09:43 -0800 Subject: [PATCH 162/293] Refactor test filtering into separate file --- busted-2.0.rc7-0.rockspec | 1 + busted-scm-0.rockspec | 1 + busted/modules/filter_loader.lua | 94 ++++++++++++++++++++++++ busted/runner.lua | 122 ++++++------------------------- 4 files changed, 119 insertions(+), 99 deletions(-) create mode 100644 busted/modules/filter_loader.lua diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index e825c4c6..4e19992e 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -49,6 +49,7 @@ build = { ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', + ['busted.modules.filter_loader'] = 'busted/modules/filter_loader.lua', ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 94aca3b2..f7ef765f 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -48,6 +48,7 @@ build = { ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', + ['busted.modules.filter_loader'] = 'busted/modules/filter_loader.lua', ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', diff --git a/busted/modules/filter_loader.lua b/busted/modules/filter_loader.lua new file mode 100644 index 00000000..f6387371 --- /dev/null +++ b/busted/modules/filter_loader.lua @@ -0,0 +1,94 @@ +return function() + local function filter(options, busted) + local getFullName = function(name) + local parent = busted.context.get() + local names = { name } + + while parent and (parent.name or parent.descriptor) and + parent.descriptor ~= 'file' do + table.insert(names, 1, parent.name or parent.descriptor) + parent = busted.context.parent(parent) + end + + return table.concat(names, ' ') + end + + local hasTag = function(name, tag) + local found = name:find('#' .. tag) + return (found ~= nil) + end + + local filterExcludeTags = function(name) + for i, tag in pairs(options.excludeTags) do + if hasTag(name, tag) then + return nil, false + end + end + return nil, true + end + + local filterTags = function(name) + local fullname = getFullName(name) + for i, tag in pairs(options.tags) do + if hasTag(fullname, tag) then + return nil, true + end + end + return nil, (#options.tags == 0) + end + + local filterOutNames = function(name) + local found = (getFullName(name):find(options.filterOut) ~= nil) + return nil, not found + end + + local filterNames = function(name) + local found = (getFullName(name):find(options.filter) ~= nil) + return nil, found + end + + local printNameOnly = function(name, fn, trace) + local fullname = getFullName(name) + if trace and trace.what == 'Lua' then + print(trace.short_src .. ':' .. trace.currentline .. ': ' .. fullname) + else + print(fullname) + end + return nil, false + end + + local ignoreAll = function() + return nil, false + end + + local skipOnError = function() + return nil, not busted.skippAll + end + + local applyFilter = function(descriptors, name, fn) + if options[name] and options[name] ~= '' then + for _, descriptor in ipairs(descriptors) do + busted.subscribe({ 'register', descriptor }, fn, { priority = 1 }) + end + end + end + + if options.list then + busted.subscribe({ 'suite', 'start' }, ignoreAll, { priority = 1 }) + busted.subscribe({ 'suite', 'end' }, ignoreAll, { priority = 1 }) + applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'list', ignoreAll) + applyFilter({ 'it', 'pending' }, 'list', printNameOnly) + end + + applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'nokeepgoing', skipOnError) + applyFilter({ 'file', 'describe', 'it', 'pending' }, 'nokeepgoing', skipOnError) + + -- The following filters are applied in reverse order + applyFilter({ 'it', 'pending' } , 'filter' , filterNames ) + applyFilter({ 'describe', 'it', 'pending' }, 'filterOut' , filterOutNames ) + applyFilter({ 'it', 'pending' } , 'tags' , filterTags ) + applyFilter({ 'describe', 'it', 'pending' }, 'excludeTags', filterExcludeTags) + end + + return filter +end diff --git a/busted/runner.lua b/busted/runner.lua index f9f331c1..d9312975 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -14,6 +14,7 @@ return function(options) local busted = require 'busted.core'() local configLoader = require 'busted.modules.configuration_loader'() + local filterLoader = require 'busted.modules.filter_loader'() local helperLoader = require 'busted.modules.helper_loader'() local outputHandlerLoader = require 'busted.modules.output_handler_loader'() @@ -126,17 +127,6 @@ return function(options) end end - local tags = {} - local excludeTags = {} - - if cliArgs.tags and cliArgs.tags ~= '' then - tags = utils.split(cliArgs.tags, ',') - end - - if cliArgs['exclude-tags'] and cliArgs['exclude-tags'] ~= '' then - excludeTags = utils.split(cliArgs['exclude-tags'], ',') - end - -- If coverage arg is passed in, load LuaCovsupport if cliArgs.coverage then luacov() @@ -162,6 +152,16 @@ return function(options) string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) end + local tags = {} + if cliArgs.tags and cliArgs.tags ~= '' then + tags = utils.split(cliArgs.tags, ',') + end + + local excludeTags = {} + if cliArgs['exclude-tags'] and cliArgs['exclude-tags'] ~= '' then + excludeTags = utils.split(cliArgs['exclude-tags'], ',') + end + -- We report an error if the same tag appears in both `options.tags` -- and `options.excluded_tags` because it does not make sense for the -- user to tell Busted to include and exclude the same tests at the @@ -175,7 +175,7 @@ return function(options) end end - -- watch for test errors + -- watch for test errors and failures local failures = 0 local errors = 0 local quitOnError = cliArgs['no-keep-going'] @@ -228,94 +228,18 @@ return function(options) busted.randomize = cliArgs['shuffle-tests'] or cliArgs.shuffle busted.randomseed = tonumber(cliArgs.seed) or os.time() - local getFullName = function(name) - local parent = busted.context.get() - local names = { name } - - while parent and (parent.name or parent.descriptor) and - parent.descriptor ~= 'file' do - table.insert(names, 1, parent.name or parent.descriptor) - parent = busted.context.parent(parent) - end - - return table.concat(names, ' ') - end - - local hasTag = function(name, tag) - local found = name:find('#' .. tag) - return (found ~= nil) - end - - local filterExcludeTags = function(name) - for i, tag in pairs(excludeTags) do - if hasTag(name, tag) then - return nil, false - end - end - return nil, true - end - - local filterTags = function(name) - local fullname = getFullName(name) - for i, tag in pairs(tags) do - if hasTag(fullname, tag) then - return nil, true - end - end - return nil, (#tags == 0) - end - - local filterOutNames = function(name) - local found = (getFullName(name):find(cliArgs['filter-out']) ~= nil) - return nil, not found - end - - local filterNames = function(name) - local found = (getFullName(name):find(cliArgs.filter) ~= nil) - return nil, found - end - - local printNameOnly = function(name, fn, trace) - local fullname = getFullName(name) - if trace and trace.what == 'Lua' then - print(trace.short_src .. ':' .. trace.currentline .. ': ' .. fullname) - else - print(fullname) - end - return nil, false - end - - local ignoreAll = function() - return nil, false - end - - local skipOnError = function() - return nil, (failures == 0 and errors == 0) - end - - local applyFilter = function(descriptors, name, fn) - if cliArgs[name] and cliArgs[name] ~= '' then - for _, descriptor in ipairs(descriptors) do - busted.subscribe({ 'register', descriptor }, fn, { priority = 1 }) - end - end - end - - if cliArgs.list then - busted.subscribe({ 'suite', 'start' }, ignoreAll, { priority = 1 }) - busted.subscribe({ 'suite', 'end' }, ignoreAll, { priority = 1 }) - applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'list', ignoreAll) - applyFilter({ 'it', 'pending' }, 'list', printNameOnly) - end - - applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'no-keep-going', skipOnError) - applyFilter({ 'file', 'describe', 'it', 'pending' }, 'no-keep-going', skipOnError) + -- Set up tag and test filter options + local filterLoaderOptions = { + tags = tags, + excludeTags = excludeTags, + filter = cliArgs.filter, + filterOut = cliArgs['filter-out'], + list = cliArgs.list, + nokeepgoing = cliArgs['no-keep-going'], + } - -- The following filters are applied in reverse order - applyFilter({ 'it', 'pending' } , 'filter' , filterNames ) - applyFilter({ 'describe', 'it', 'pending' }, 'filter-out' , filterOutNames ) - applyFilter({ 'it', 'pending' } , 'tags' , filterTags ) - applyFilter({ 'describe', 'it', 'pending' }, 'exclude-tags', filterExcludeTags) + -- Load tag and test filters + filterLoader(filterLoaderOptions, busted) -- Set up helper script if cliArgs.helper and cliArgs.helper ~= '' then From 2859d60543144fc54e248a3d9d1e1fea66b8752d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Feb 2015 16:15:34 -0800 Subject: [PATCH 163/293] Allow list type options to be specified many times This allows options, that accept a delimiter separated list of arguments, to be specified multiple times, such that each occurrence of the option appends to previous occurrences of that option. For example: $ busted -t tag1,tag2 -t tag3 is equivalent to $ busted -t tag1,tag2,tag3 and, similarly $ busted --lpath="./" --lpath=./src" is equivalent to $ busted --lpath="./;./src" --- busted/runner.lua | 64 ++++++++++++++++++++++++++++++----------------- spec/cl_spec.lua | 18 +++++++++++++ 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index d9312975..95618e9a 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -1,6 +1,7 @@ -- Busted command-line runner local path = require 'pl.path' +local tablex = require 'pl.tablex' local term = require 'term' local utils = require 'busted.utils' local loaded = false @@ -61,6 +62,31 @@ return function(options) osexit(0, true) end + local function processList(key, value, altkey, opt) + local list = cliArgsParsed[key] or {} + tablex.insertvalues(list, utils.split(value, ',')) + processOption(key, list, altkey, opt) + return true + end + + local function append(s1, s2, sep) + local sep = sep or '' + if not s1 then return s2 end + return s1 .. sep .. s2 + end + + local function processLoaders(key, value, altkey, opt) + local loaders = append(cliArgsParsed[key], value, ',') + processOption(key, loaders, altkey, opt) + return true + end + + local function processPath(key, value, altkey, opt) + local lpath = append(cliArgsParsed[key], value, ';') + processOption(key, lpath, altkey, opt) + return true + end + -- Load up the command-line interface options cli:set_name(path.basename(fileName)) cli:add_flag('--version', 'prints the program version and exits', processVersion) @@ -73,21 +99,21 @@ return function(options) cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) cli:add_option('-d, --cwd=cwd', 'path to current working directory', './', processOption) - cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', nil, processOption) - cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', nil, processOption) + cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) + cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', nil, processOption) cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', nil, processOption) - cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processOption) - cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processOption) + cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processPath) + cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processPath) cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', processNumber) cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processNumber) cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) - cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processOption) + cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processLoaders) cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) - cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', nil, processOption) - cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', nil, processOption) + cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) + cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', processOption) cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) @@ -125,6 +151,8 @@ return function(options) else cliArgs = config end + else + cliArgs = tablex.merge(cliArgs, cliArgsParsed, true) end -- If coverage arg is passed in, load LuaCovsupport @@ -152,22 +180,12 @@ return function(options) string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) end - local tags = {} - if cliArgs.tags and cliArgs.tags ~= '' then - tags = utils.split(cliArgs.tags, ',') - end - - local excludeTags = {} - if cliArgs['exclude-tags'] and cliArgs['exclude-tags'] ~= '' then - excludeTags = utils.split(cliArgs['exclude-tags'], ',') - end - -- We report an error if the same tag appears in both `options.tags` -- and `options.excluded_tags` because it does not make sense for the -- user to tell Busted to include and exclude the same tests at the -- same time. - for _, excluded in pairs(excludeTags) do - for _, included in pairs(tags) do + for _, excluded in pairs(cliArgs['exclude-tags']) do + for _, included in pairs(cliArgs.tags) do if excluded == included then print('Error: Cannot use --tags and --exclude-tags for the same tags') osexit(1, true) @@ -212,7 +230,7 @@ return function(options) suppressPending = cliArgs['suppress-pending'], language = cliArgs.lang, deferPrint = cliArgs['defer-print'], - arguments = cliArgs.Xoutput and utils.split(cliArgs.Xoutput, ',') or {} + arguments = cliArgs.Xoutput } local opath = utils.normpath(path.join(fpath, cliArgs.output)) @@ -230,8 +248,8 @@ return function(options) -- Set up tag and test filter options local filterLoaderOptions = { - tags = tags, - excludeTags = excludeTags, + tags = cliArgs.tags, + excludeTags = cliArgs['exclude-tags'], filter = cliArgs.filter, filterOut = cliArgs['filter-out'], list = cliArgs.list, @@ -246,7 +264,7 @@ return function(options) local helperOptions = { verbose = cliArgs.verbose, language = cliArgs.lang, - arguments = cliArgs.Xhelper and utils.split(cliArgs.Xhelper, ',') or {} + arguments = cliArgs.Xhelper } local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index d4ccbbc6..f591f1e3 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -71,6 +71,9 @@ describe('Tests the busted command-line options', function() success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1,tag2') assert.is_false(success) assert.is_equal(4, exitcode) + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1 --tags=tag2') + assert.is_false(success) + assert.is_equal(4, exitcode) error_end() end) @@ -83,6 +86,9 @@ describe('Tests the busted command-line options', function() success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') assert.is_false(success) assert.is_equal(2, exitcode) + success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --exclude-tags=tag2 --exclude-tags=dtag1,dtag2') + assert.is_false(success) + assert.is_equal(2, exitcode) error_end() end) @@ -722,6 +728,12 @@ describe('Tests Xoutput commandline option', function() local timestamp = result:match('^%[(.-)]') assert.is_equal('10:17:36', timestamp) end) + + it('forwards multiple options to output handler using multiple -Xoutput', function() + local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua -Xoutput "--time" -Xoutput "--time-format=!%H:%M:%S" --pattern=cl_success.lua$') + local timestamp = result:match('^%[(.-)]') + assert.is_equal('10:17:36', timestamp) + end) end) describe('Tests Xhelper commandline option', function() @@ -741,6 +753,12 @@ describe('Tests Xhelper commandline option', function() assert.is_false(success) assert.is_equal(2, exitcode) end) + + it('forwards multiple options to helper script using multiple -Xhelper', function() + local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" -Xhelper "--fail-after-each" --pattern=cl_success.lua$') + assert.is_false(success) + assert.is_equal(2, exitcode) + end) end) describe('Tests helper script', function() From addce802c85a73745794b657aa711659d7a4946d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 27 Feb 2015 17:39:53 -0800 Subject: [PATCH 164/293] Refactor CLI parsing into a CLI module --- busted-2.0.rc7-0.rockspec | 3 +- busted-scm-0.rockspec | 3 +- busted/modules/cli.lua | 195 +++++++++++++++++ busted/modules/configuration_loader.lua | 4 +- busted/runner.lua | 168 ++------------ spec/.hidden/.busted | 18 ++ spec/modules/cli_spec.lua | 277 ++++++++++++++++++++++++ 7 files changed, 512 insertions(+), 156 deletions(-) create mode 100644 busted/modules/cli.lua create mode 100644 spec/.hidden/.busted create mode 100644 spec/modules/cli_spec.lua diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index 4e19992e..09379f98 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.3-3', + 'lua_cliargs >= 2.4-1', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', @@ -50,6 +50,7 @@ build = { ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', ['busted.modules.filter_loader'] = 'busted/modules/filter_loader.lua', + ['busted.modules.cli'] = 'busted/modules/cli.lua', ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index f7ef765f..051ab92b 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.3-3', + 'lua_cliargs >= 2.4-1', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', @@ -49,6 +49,7 @@ build = { ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', ['busted.modules.filter_loader'] = 'busted/modules/filter_loader.lua', + ['busted.modules.cli'] = 'busted/modules/cli.lua', ['busted.modules.files.lua'] = 'busted/modules/files/lua.lua', ['busted.modules.files.moonscript'] = 'busted/modules/files/moonscript.lua', diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua new file mode 100644 index 00000000..88d83c42 --- /dev/null +++ b/busted/modules/cli.lua @@ -0,0 +1,195 @@ +local utils = require 'busted.utils' +local path = require 'pl.path' +local tablex = require 'pl.tablex' + +return function(options) + local appName = '' + local options = options or {} + local cli = require 'cliargs' + + local configLoader = require 'busted.modules.configuration_loader'() + + -- Default cli arg values + local defaultOutput = options.defaultOutput + local defaultLoaders = 'lua,moonscript' + local defaultPattern = '_spec' + local defaultSeed = 'os.time()' + local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' + local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' + + local cliArgsParsed = {} + + local function fixupList(values, sep) + local sep = sep or ',' + local list = type(values) == 'table' and values or { values } + local olist = {} + for _, v in ipairs(list) do + tablex.insertvalues(olist, utils.split(v, sep)) + end + return olist + end + + local function processOption(key, value, altkey, opt) + if altkey then cliArgsParsed[altkey] = value end + cliArgsParsed[key] = value + return true + end + + local function processArg(key, value) + cliArgsParsed[key] = value + return true + end + + local function processNumber(key, value, altkey, opt) + local number = tonumber(value) + if not number then + return nil, 'argument to ' .. opt:gsub('=.*', '') .. ' must be a number' + end + if altkey then cliArgsParsed[altkey] = number end + cliArgsParsed[key] = number + return true + end + + local function processList(key, value, altkey, opt) + local list = cliArgsParsed[key] or {} + tablex.insertvalues(list, utils.split(value, ',')) + processOption(key, list, altkey, opt) + return true + end + + local function append(s1, s2, sep) + local sep = sep or '' + if not s1 then return s2 end + return s1 .. sep .. s2 + end + + local function processLoaders(key, value, altkey, opt) + local loaders = append(cliArgsParsed[key], value, ',') + processOption(key, loaders, altkey, opt) + return true + end + + local function processPath(key, value, altkey, opt) + local lpath = append(cliArgsParsed[key], value, ';') + processOption(key, lpath, altkey, opt) + return true + end + + -- Load up the command-line interface options + cli:add_flag('--version', 'prints the program version and exits', processOption) + + if options.batch then + cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1, processArg) + + cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) + end + + cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) + cli:add_option('-d, --cwd=cwd', 'path to current working directory', './', processOption) + cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) + cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) + cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', nil, processOption) + cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', nil, processOption) + cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processPath) + cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processPath) + cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) + cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', processNumber) + cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processNumber) + cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) + cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processLoaders) + cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) + + cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) + cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) + + cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', processOption) + cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) + cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) + cli:add_flag('-l, --list', 'list the names of all tests instead of running them', processOption) + cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) + cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) + cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) + cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) + cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) + cli:add_flag('--sort', 'sort file and test order (--sort-tests and --sort-files)', processOption) + cli:add_flag('--sort-files', 'sort file execution order', processOption) + cli:add_flag('--sort-tests', 'sort test order within a file', processOption) + cli:add_flag('--suppress-pending', 'suppress `pending` test output', processOption) + cli:add_flag('--defer-print', 'defer print to when test suite is complete', processOption) + + local function parse(args) + -- Parse the cli arguments + local cliArgs, cliErr = cli:parse(args, true) + if not cliArgs then + return nil, cliErr + end + + -- Load busted config file if available + local configFile = { } + local bustedConfigFilePath = utils.normpath(path.join(cliArgs.cwd, '.busted')) + local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) + if bustedConfigFile then + local config, err = configLoader(configFile, cliArgsParsed, cliArgs) + if err then + return nil, appName .. ': error: ' .. err + else + cliArgs = config + end + else + cliArgs = tablex.merge(cliArgs, cliArgsParsed, true) + end + + local fpath = utils.normpath(cliArgs.cwd):gsub('[/%\\]$', '') + + -- Add additional package paths based on lpath and cpath cliArgs + if #cliArgs.lpath > 0 then + local lpath = cliArgs.lpath + lpath = lpath:gsub('^%.([/%\\])', fpath .. '%1') + lpath = lpath:gsub(';%.([/%\\])', ';' .. fpath .. '%1') + cliArgs.lpath = lpath + cliArgs.m = lpath + end + + if #cliArgs.cpath > 0 then + local cpath = cliArgs.cpath + cpath = cpath:gsub('^%.([/%\\])', fpath .. '%1') + cpath = cpath:gsub(';%.([/%\\])', ';' .. fpath .. '%1') + cliArgs.cpath = cpath + end + + -- Fixup options in case options from config file are not of the right form + cliArgs.tags = fixupList(cliArgs.tags) + cliArgs.t = cliArgs.tags + cliArgs['exclude-tags'] = fixupList(cliArgs['exclude-tags']) + cliArgs.loaders = fixupList(cliArgs.loaders) + cliArgs.Xoutput = fixupList(cliArgs.Xoutput) + cliArgs.Xhelper = fixupList(cliArgs.Xhelper) + + -- We report an error if the same tag appears in both `options.tags` + -- and `options.excluded_tags` because it does not make sense for the + -- user to tell Busted to include and exclude the same tests at the + -- same time. + for _, excluded in pairs(cliArgs['exclude-tags']) do + for _, included in pairs(cliArgs.tags) do + if excluded == included then + return nil, appName .. ': error: Cannot use --tags and --exclude-tags for the same tags' + end + end + end + + cliArgs['repeat'] = tonumber(cliArgs['repeat']) + + return cliArgs + end + + return { + set_name = function(self, name) + appName = name + return cli:set_name(name) + end, + + parse = function(self, args) + return parse(args) + end + } +end diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index f437a04c..95593e3b 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -18,9 +18,7 @@ return function() else return config, 'Task `' .. run .. '` not found, or not a table.' end - end - - if type(configFile.default) == 'table' then + elseif type(configFile.default) == 'table' then config = tablex.merge(configFile.default, config, true) end diff --git a/busted/runner.lua b/busted/runner.lua index 95618e9a..7d37257c 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -1,160 +1,50 @@ -- Busted command-line runner local path = require 'pl.path' -local tablex = require 'pl.tablex' local term = require 'term' local utils = require 'busted.utils' +local osexit = require 'busted.compatibility'.osexit local loaded = false return function(options) if loaded then return else loaded = true end - local opt = options or {} - local isBatch = opt.batch - local cli = require 'cliargs' + local options = options or {} + options.defaultOutput = term.isatty(io.stdout) and 'utfTerminal' or 'plainTerminal' + local busted = require 'busted.core'() - local configLoader = require 'busted.modules.configuration_loader'() + local cli = require 'busted.modules.cli'(options) local filterLoader = require 'busted.modules.filter_loader'() local helperLoader = require 'busted.modules.helper_loader'() local outputHandlerLoader = require 'busted.modules.output_handler_loader'() local luacov = require 'busted.modules.luacov'() - local osexit = require 'busted.compatibility'.osexit - require 'busted'(busted) - -- Default cli arg values - local defaultOutput = term.isatty(io.stdout) and 'utfTerminal' or 'plainTerminal' - local defaultLoaders = 'lua,moonscript' - local defaultPattern = '_spec' - local defaultSeed = 'os.time()' - local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' - local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local level = 2 local info = debug.getinfo(level, 'Sf') local source = info.source local fileName = source:sub(1,1) == '@' and source:sub(2) or source - local cliArgsParsed = {} - - local function processOption(key, value, altkey, opt) - if altkey then cliArgsParsed[altkey] = value end - cliArgsParsed[key] = value - return true - end - - local function processNumber(key, value, altkey, opt) - local number = tonumber(value) - if not number then - return nil, 'argument to ' .. opt:gsub('=.*', '') .. ' must be a number' - end - if altkey then cliArgsParsed[altkey] = number end - cliArgsParsed[key] = number - return true + -- Parse the cli arguments + cli:set_name(path.basename(fileName)) + local cliArgs, err = cli:parse(arg) + if not cliArgs then + print(err) + osexit(1, true) end - local function processVersion() + if cliArgs.version then -- Return early if asked for the version print(busted.version) osexit(0, true) end - local function processList(key, value, altkey, opt) - local list = cliArgsParsed[key] or {} - tablex.insertvalues(list, utils.split(value, ',')) - processOption(key, list, altkey, opt) - return true - end - - local function append(s1, s2, sep) - local sep = sep or '' - if not s1 then return s2 end - return s1 .. sep .. s2 - end - - local function processLoaders(key, value, altkey, opt) - local loaders = append(cliArgsParsed[key], value, ',') - processOption(key, loaders, altkey, opt) - return true - end - - local function processPath(key, value, altkey, opt) - local lpath = append(cliArgsParsed[key], value, ';') - processOption(key, lpath, altkey, opt) - return true - end - - -- Load up the command-line interface options - cli:set_name(path.basename(fileName)) - cli:add_flag('--version', 'prints the program version and exits', processVersion) - - if isBatch then - cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1) - - cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) - end - - cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) - cli:add_option('-d, --cwd=cwd', 'path to current working directory', './', processOption) - cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) - cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) - cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', nil, processOption) - cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', nil, processOption) - cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processPath) - cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processPath) - cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) - cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', processNumber) - cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processNumber) - cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) - cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processLoaders) - cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) - - cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) - cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) - - cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', processOption) - cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) - cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) - cli:add_flag('-l, --list', 'list the names of all tests instead of running them', processOption) - cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) - cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) - cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) - cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) - cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) - cli:add_flag('--sort', 'sort file and test order (--sort-tests and --sort-files)', processOption) - cli:add_flag('--sort-files', 'sort file execution order', processOption) - cli:add_flag('--sort-tests', 'sort test order within a file', processOption) - cli:add_flag('--suppress-pending', 'suppress `pending` test output', processOption) - cli:add_flag('--defer-print', 'defer print to when test suite is complete', processOption) - - -- Parse the cli arguments - local cliArgs = cli:parse(arg) - if not cliArgs then - osexit(1, true) - end - -- Load current working directory local fpath = utils.normpath(cliArgs.cwd) - -- Load busted config file if available - local configFile = { } - local bustedConfigFilePath = utils.normpath(path.join(fpath, '.busted')) - local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) - if bustedConfigFile then - local config, err = configLoader(configFile, cliArgsParsed, cliArgs) - if err then - print('Error: ' .. err) - osexit(1, true) - else - cliArgs = config - end - else - cliArgs = tablex.merge(cliArgs, cliArgsParsed, true) - end - -- If coverage arg is passed in, load LuaCovsupport if cliArgs.coverage then luacov() @@ -162,35 +52,11 @@ return function(options) -- Add additional package paths based on lpath and cpath cliArgs if #cliArgs.lpath > 0 then - lpathprefix = cliArgs.lpath - lpathprefix = lpathprefix:gsub('^%.([/%\\])', fpath .. '%1') - lpathprefix = lpathprefix:gsub(';%.([/%\\])', ';' .. fpath .. '%1') - package.path = (lpathprefix .. ';' .. package.path):gsub(';;',';') + package.path = (cliArgs.lpath .. ';' .. package.path):gsub(';;',';') end if #cliArgs.cpath > 0 then - cpathprefix = cliArgs.cpath - cpathprefix = cpathprefix:gsub('^%.([/%\\])', fpath .. '%1') - cpathprefix = cpathprefix:gsub(';%.([/%\\])', ';' .. fpath .. '%1') - package.cpath = (cpathprefix .. ';' .. package.cpath):gsub(';;',';') - end - - local loaders = {} - if #cliArgs.loaders > 0 then - string.gsub(cliArgs.loaders, '([^,]+)', function(c) loaders[#loaders+1] = c end) - end - - -- We report an error if the same tag appears in both `options.tags` - -- and `options.excluded_tags` because it does not make sense for the - -- user to tell Busted to include and exclude the same tests at the - -- same time. - for _, excluded in pairs(cliArgs['exclude-tags']) do - for _, included in pairs(cliArgs.tags) do - if excluded == included then - print('Error: Cannot use --tags and --exclude-tags for the same tags') - osexit(1, true) - end - end + package.cpath = (cliArgs.cpath .. ';' .. package.cpath):gsub(';;',';') end -- watch for test errors and failures @@ -234,7 +100,7 @@ return function(options) } local opath = utils.normpath(path.join(fpath, cliArgs.output)) - local outputHandler = outputHandlerLoader(cliArgs.output, opath, outputHandlerOptions, busted, defaultOutput) + local outputHandler = outputHandlerLoader(cliArgs.output, opath, outputHandlerOptions, busted, options.defaultOutput) outputHandler:subscribe(outputHandlerOptions) if cliArgs['enable-sound'] then @@ -283,7 +149,7 @@ return function(options) -- Load test directory local rootFile = cliArgs.ROOT and utils.normpath(path.join(fpath, cliArgs.ROOT)) or fileName local pattern = cliArgs.pattern - local testFileLoader = require 'busted.modules.test_file_loader'(busted, loaders, testFileLoaderOptions) + local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders, testFileLoaderOptions) local fileList = testFileLoader(rootFile, pattern) if not cliArgs.ROOT then @@ -292,7 +158,7 @@ return function(options) getmetatable(file.run).__call = info.func end - local runs = tonumber(cliArgs['repeat']) or 1 + local runs = cliArgs['repeat'] local execute = require 'busted.execute'(busted) execute(runs, { seed = cliArgs.seed }) diff --git a/spec/.hidden/.busted b/spec/.hidden/.busted new file mode 100644 index 00000000..d4555559 --- /dev/null +++ b/spec/.hidden/.busted @@ -0,0 +1,18 @@ +return { + default = { + ['tags'] = {'tag11','tag22','tag33'}, + ['exclude-tags'] = {'etag11','etag22','etag33'}, + ['pattern'] = '_spec%.lua$', + ['loaders'] = 'terra,moonscript', + ['Xoutput'] = '-f,--flag', + ['Xhelper'] = '-v,--verbose', + }, + test = { + ['tags'] = 'test1,test2,test3', + ['exclude-tags'] = 'etest1,etest2,etest3', + ['pattern'] = '_test%.lua$', + ['loaders'] = {'lua','terra'}, + ['Xoutput'] = {'-s','--sound'}, + ['Xhelper'] = {'-t','--print'}, + } +} diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua new file mode 100644 index 00000000..05bb1691 --- /dev/null +++ b/spec/modules/cli_spec.lua @@ -0,0 +1,277 @@ +local path = require 'pl.path' + +describe('Tests command-line interface', function() + it('default options', function() + local defaultOutput = 'default_output_handler' + local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' + local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' + local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local args = cli:parse({}) + assert.is_equal(defaultOutput, args.o) + assert.is_equal(defaultOutput, args.output) + assert.is_equal('spec', args.ROOT) + assert.is_equal('./', args.d) + assert.is_equal('./', args.cwd) + assert.is_equal('_spec', args.p) + assert.is_equal('_spec', args.pattern) + assert.is_equal('os.time()', args.seed) + assert.is_equal('en', args.lang) + assert.is_equal(1, args['repeat']) + assert.is_equal(lpath, args.m) + assert.is_equal(lpath, args.lpath) + assert.is_equal(cpath, args.cpath) + assert.is_nil(args.c) + assert.is_nil(args.coverage) + assert.is_nil(args.version) + assert.is_nil(args.v) + assert.is_nil(args.verbose) + assert.is_nil(args.l) + assert.is_nil(args.list) + assert.is_nil(args.s) + assert.is_nil(args['enable-sound']) + assert.is_nil(args['no-keep-going']) + assert.is_nil(args['no-recursive']) + assert.is_nil(args['suppress-pending']) + assert.is_nil(args['defer-print']) + assert.is_nil(args.shuffle) + assert.is_nil(args['shuffle-files']) + assert.is_nil(args.sort) + assert.is_nil(args['sort-files']) + assert.is_nil(args.r) + assert.is_nil(args.run) + assert.is_nil(args.filter) + assert.is_nil(args['filter-out']) + assert.is_nil(args.helper) + assert.is_same({}, args.t) + assert.is_same({}, args.tags) + assert.is_same({}, args['exclude-tags']) + assert.is_same({}, args.Xoutput) + assert.is_same({}, args.Xhelper) + assert.is_same({'lua', 'moonscript'}, args.loaders) + end) + + it('standalone options disables ROOT and --pattern', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({}) + assert.is_nil(args.ROOT) + assert.is_nil(args.p) + assert.is_nil(args.pattern) + end) + + it('specify flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '-v', '--version', '--coverage', '--defer-print', '--suppress-pending' }) + assert.is_true(args.v) + assert.is_true(args.verbose) + assert.is_true(args.version) + assert.is_true(args.coverage) + assert.is_true(args['defer-print']) + assert.is_true(args['suppress-pending']) + end) + + it('specify more flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '-s', '--list', '--no-keep-going', '--no-recursive' }) + assert.is_true(args.s) + assert.is_true(args['enable-sound']) + assert.is_true(args.l) + assert.is_true(args.list) + assert.is_true(args['no-keep-going']) + assert.is_true(args['no-recursive']) + end) + + it('specify shuffle flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--shuffle', '--shuffle-files', '--shuffle-tests' }) + assert.is_true(args.shuffle) + assert.is_true(args['shuffle-files']) + assert.is_true(args['shuffle-tests']) + end) + + it('specify short flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--sort', '--sort-files', '--sort-tests' }) + assert.is_true(args.sort) + assert.is_true(args['sort-files']) + assert.is_true(args['sort-tests']) + end) + + it('specify ROOT arg and --pattern', function() + local cli = require 'busted.modules.cli'({ batch = true }) + local args = cli:parse({ '-p', 'match_files', 'root_is_here' }) + assert.is_equal('root_is_here', args.ROOT) + assert.is_equal('match_files', args.p) + assert.is_equal('match_files', args.pattern) + end) + + it('specify --cwd', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--cwd=/path/to/dir' }) + assert.is_equal('/path/to/dir', args.d) + assert.is_equal('/path/to/dir', args.cwd) + end) + + it('specify --run', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--run=task' }) + assert.is_equal('task', args.r) + assert.is_equal('task', args.run) + end) + + it('specify --lang', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--lang=fr' }) + assert.is_equal('fr', args.lang) + end) + + it('specify --repeat', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--repeat=23' }) + assert.is_equal(23, args['repeat']) + end) + + it('specify output library', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '-o', 'output_handler', '-Xoutput', '--flag,-f', '-Xoutput', '--opt=val' }) + assert.is_equal('output_handler', args.o) + assert.is_equal('output_handler', args.output) + assert.is_same({'--flag', '-f', '--opt=val'}, args.Xoutput) + end) + + it('specify helper script', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--helper=helper_script', '-Xhelper', '--flag,-f', '-Xhelper', '--opt=val' }) + assert.is_equal('helper_script', args.helper) + assert.is_same({'--flag', '-f', '--opt=val'}, args.Xhelper) + end) + + it('specify --tags and --exclude-tags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--tags=tag1,tag2', '-t', 'tag3', '--exclude-tags=etag1', '--exclude-tags=etag2,etag3' }) + assert.is_same({'tag1', 'tag2', 'tag3'}, args.t) + assert.is_same({'tag1', 'tag2', 'tag3'}, args.tags) + assert.is_same({'etag1', 'etag2', 'etag3'}, args['exclude-tags']) + end) + + it('specify --filter and --filter-out', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--filter=_filt', '--filter-out=_filterout' }) + assert.is_equal('_filt', args.filter) + assert.is_equal('_filterout', args['filter-out']) + end) + + it('specify --loaders', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--loaders=load1,load2', '--loaders=load3' }) + assert.is_same({'load1', 'load2', 'load3'}, args.loaders) + end) + + it('specify --lpath', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '-d', '/root', '--lpath=./path1/?.lua', '-m', './path2/?.lua' }) + assert.is_equal('/root/path1/?.lua;/root/path2/?.lua', args.m) + assert.is_equal('/root/path1/?.lua;/root/path2/?.lua', args.lpath) + end) + + it('specify --cpath', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '-d', '/croot', '--lpath=./path1/?.so', '-m', './path2/?.so' }) + assert.is_equal('/croot/path1/?.so;/croot/path2/?.so', args.m) + assert.is_equal('/croot/path1/?.so;/croot/path2/?.so', args.lpath) + end) +end) + +describe('Tests using .busted tasks', function() + it('default options', function() + local defaultOutput = 'default_output_handler' + local lpath = 'spec/.hidden/src/?.lua;spec/.hidden/src/?/?.lua;spec/.hidden/src/?/init.lua' + local cpath = path.is_windows and 'spec/.hidden/csrc/?.dll;spec/.hidden/csrc/?/?.dll;' or 'spec/.hidden/csrc/?.so;spec/.hidden/csrc/?/?.so;' + local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local args = cli:parse({ '--cwd=spec/.hidden' }) + assert.is_equal(defaultOutput, args.o) + assert.is_equal(defaultOutput, args.output) + assert.is_equal('spec', args.ROOT) + assert.is_equal('spec/.hidden', args.d) + assert.is_equal('spec/.hidden', args.cwd) + assert.is_equal('_spec', args.p) + assert.is_equal('_spec%.lua$', args.pattern) + assert.is_equal('os.time()', args.seed) + assert.is_equal('en', args.lang) + assert.is_equal(1, args['repeat']) + assert.is_equal(lpath, args.m) + assert.is_equal(lpath, args.lpath) + assert.is_equal(cpath, args.cpath) + assert.is_nil(args.c) + assert.is_nil(args.coverage) + assert.is_nil(args.version) + assert.is_nil(args.v) + assert.is_nil(args.verbose) + assert.is_nil(args.l) + assert.is_nil(args.list) + assert.is_nil(args.s) + assert.is_nil(args['enable-sound']) + assert.is_nil(args['no-keep-going']) + assert.is_nil(args['no-recursive']) + assert.is_nil(args['suppress-pending']) + assert.is_nil(args['defer-print']) + assert.is_nil(args.shuffle) + assert.is_nil(args['shuffle-files']) + assert.is_nil(args.sort) + assert.is_nil(args['sort-files']) + assert.is_nil(args.r) + assert.is_nil(args.run) + assert.is_nil(args.filter) + assert.is_nil(args['filter-out']) + assert.is_nil(args.helper) + assert.is_same({'tag11', 'tag22', 'tag33'}, args.t) + assert.is_same({'tag11', 'tag22', 'tag33'}, args.tags) + assert.is_same({'etag11', 'etag22', 'etag33'}, args['exclude-tags']) + assert.is_same({'-f', '--flag'}, args.Xoutput) + assert.is_same({'-v', '--verbose'}, args.Xhelper) + assert.is_same({'terra', 'moonscript'}, args.loaders) + end) + + it('load configuration options', function() + local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local args = cli:parse({ '--cwd=spec/.hidden', '--run=test' }) + assert.is_equal('_test%.lua$', args.pattern) + assert.is_same({'test1', 'test2', 'test3'}, args.tags) + assert.is_same({'etest1', 'etest2', 'etest3'}, args['exclude-tags']) + assert.is_same({'-s','--sound'}, args.Xoutput) + assert.is_same({'-t', '--print'}, args.Xhelper) + assert.is_same({'lua', 'terra'}, args.loaders) + end) + + it('load configuration options and override with command-line', function() + local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local args = cli:parse({ '--cwd=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--loaders=moonscript' }) + assert.is_equal('patt', args.pattern) + assert.is_same({'tag1'}, args.tags) + assert.is_same({'etest1', 'etest2', 'etest3'}, args['exclude-tags']) + assert.is_same({'-s','--sound'}, args.Xoutput) + assert.is_same({'-t', '--print'}, args.Xhelper) + assert.is_same({'moonscript'}, args.loaders) + end) +end) + +describe('Tests command-line parse errors', function() + before_each(function() + package.loaded['cliargs'] = nil + end) + + it('with invalid --repeat value', function() + local cli = require 'busted.modules.cli'() + cli:set_name('myapp') + local args, err = cli:parse({ '--repeat=abc'}) + assert.is_nil(args) + assert.is_equal('myapp: error: argument to --repeat must be a number; re-run with --help for usage.', err) + end) + + it('with same tag for --tags and --exclude-tags', function() + local cli = require 'busted.modules.cli'() + cli:set_name('myapp') + local args, err = cli:parse({ '--tags=tag1', '--exclude-tags=tag1' }) + assert.is_nil(args) + assert.is_equal('myapp: error: Cannot use --tags and --exclude-tags for the same tags', err) + end) +end) From 263f6cf5afbff7245363e0805759d24996fe3a5f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 1 Mar 2015 20:33:13 -0800 Subject: [PATCH 165/293] Refactor error/failure output Add random seed information to the structured output populated by the base output handler. Output random seed info in the derived output handlers instead of manipulating the error/failure message in the base output handler. --- busted/outputHandlers/TAP.lua | 1 + busted/outputHandlers/base.lua | 31 ++++++++----------------- busted/outputHandlers/junit.lua | 18 ++++++++------ busted/outputHandlers/plainTerminal.lua | 8 +++---- busted/outputHandlers/utfTerminal.lua | 8 +++---- spec/cl_spec.lua | 4 ++-- 6 files changed, 32 insertions(+), 38 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index b46350ec..08ead59f 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -29,6 +29,7 @@ return function(options, busted) print(failure:format(counter, t.name)) print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) + if t.randomseed then print('# Random seed: ' .. t.randomseed) end print('# Failure message: ' .. message:gsub('\n', '\n# ')) if options.verbose and trace.traceback then print('# ' .. trace.traceback:gsub('^\n', '', 1):gsub('\n', '\n# ')) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 5043c0a2..67b7aa63 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -55,6 +55,7 @@ return function(busted) element = element, name = handler.getFullName(element), message = message, + randomseed = parent and parent.randomseed, isError = isError } formatted.element.trace = element.trace or debug @@ -100,7 +101,6 @@ return function(busted) end handler.baseTestEnd = function(element, parent, status, debug) - local isError local insertTable if status == 'success' then @@ -110,15 +110,16 @@ return function(busted) insertTable = handler.pendings handler.pendingsCount = handler.pendingsCount + 1 elseif status == 'failure' then - insertTable = handler.failures - -- failure count already incremented in error handler + -- failure already saved in failure handler + handler.failuresCount = handler.failuresCount + 1 + return nil, true elseif status == 'error' then - -- error count already incremented in error handler + -- error count already incremented and saved in error handler insertTable = handler.errors - isError = true + return nil, true end - local formatted = handler.format(element, parent, element.message, debug, isError) + local formatted = handler.format(element, parent, element.message, debug) local id = tostring(element) if handler.inProgress[id] then @@ -134,33 +135,21 @@ return function(busted) return nil, true end - local function saveInProgress(element, message, debug) + handler.basePending = function(element, parent, message, debug) local id = tostring(element) handler.inProgress[id].message = message handler.inProgress[id].trace = debug - end - - local function saveError(element, parent, message, debug) - if parent.randomseed then - message = 'Random Seed: ' .. parent.randomseed .. '\n' .. message - end - saveInProgress(element, message, debug) - end - - handler.basePending = function(element, parent, message, debug) - saveInProgress(element, message, debug) return nil, true end handler.baseTestFailure = function(element, parent, message, debug) - handler.failuresCount = handler.failuresCount + 1 - saveError(element, parent, message, debug) + table.insert(handler.failures, handler.format(element, parent, message, debug)) return nil, true end handler.baseTestError = function(element, parent, message, debug) handler.errorsCount = handler.errorsCount + 1 - saveError(element, parent, message, debug) + table.insert(handler.errors, handler.format(element, parent, message, debug, true)) return nil, true end diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 36e78936..f6666515 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -14,6 +14,7 @@ return function(options, busted) }) } local stack = {} + local testcase_node local testStartTime handler.suiteStart = function(count, total) @@ -60,15 +61,11 @@ return function(options, busted) end local function testStatus(element, parent, message, status, trace) - local testcase_node = xml.new('testcase', { - classname = element.trace.short_src .. ':' .. element.trace.currentline, - name = handler.getFullName(element), - time = elapsed(testStartTime) - }) - top.xml_doc:add_direct_child(testcase_node) - if status ~= 'success' then testcase_node:addtag(status) + if status ~= 'pending' and parent and parent.randomseed then + testcase_node:text('Random seed: ' .. parent.randomseed .. '\n') + end if message then testcase_node:text(message) end if trace and trace.traceback then testcase_node:text(trace.traceback) end testcase_node:up() @@ -77,12 +74,19 @@ return function(options, busted) handler.testStart = function(element, parent) testStartTime = socket.gettime() + testcase_node = xml.new('testcase', { + classname = element.trace.short_src .. ':' .. element.trace.currentline, + name = handler.getFullName(element), + }) + top.xml_doc:add_direct_child(testcase_node) return nil, true end handler.testEnd = function(element, parent, status) top.xml_doc.attr.tests = top.xml_doc.attr.tests + 1 + testcase_node.time = elapsed(testStartTime) + testStartTime = nil if status == 'success' then testStatus(element, parent, nil, 'success') diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index fc4b092f..0632558c 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -27,13 +27,13 @@ return function(options, busted) end local failureMessage = function(failure) - local string + local string = failure.randomseed and ('Random seed: ' .. failure.randomseed .. '\n') or '' if type(failure.message) == 'string' then - string = failure.message + string = string .. failure.message elseif failure.message == nil then - string = 'Nil error' + string = string .. 'Nil error' else - string = pretty.write(failure.message) + string = string .. pretty.write(failure.message) end return string diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 9aa8e714..cc6d6782 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -28,13 +28,13 @@ return function(options, busted) end local failureMessage = function(failure) - local string + local string = failure.randomseed and ('Random seed: ' .. failure.randomseed .. '\n') or '' if type(failure.message) == 'string' then - string = failure.message + string = string .. failure.message elseif failure.message == nil then - string = 'Nil error' + string = string .. 'Nil error' else - string = pretty.write(failure.message) + string = string .. pretty.write(failure.message) end return string diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index f591f1e3..3fea691f 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -628,7 +628,7 @@ describe('Tests random seed through the commandline', function() it('test failure outputs random seed value', function() error_start() local result = run(busted_cmd .. ' --seed=789 --pattern=cl_random_seed.lua$') - local seed = result:match('Random Seed: (%d+)\n') + local seed = result:match('Random seed: (%d+)\n') assert.is_equal(789, tonumber(seed)) error_end() end) @@ -636,7 +636,7 @@ describe('Tests random seed through the commandline', function() it('test non-randomized failure does not output seed value', function() error_start() local result = run(busted_cmd .. ' --seed=789 --pattern=cl_two_failures.lua$') - local seed = result:match('Random Seed:') + local seed = result:match('Random seed:') assert.is_equal(nil, seed) error_end() end) From 12c4703e0908e537ca76974d9563bdb427253a0d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 4 Mar 2015 23:14:18 -0800 Subject: [PATCH 166/293] Refactor context block execution --- busted/block.lua | 81 ++++++++++++++++++++++++++++++++++++++++++++-- busted/core.lua | 75 ------------------------------------------ busted/execute.lua | 6 ++-- busted/init.lua | 8 ++--- spec/core_spec.lua | 6 ++++ 5 files changed, 93 insertions(+), 83 deletions(-) diff --git a/busted/block.lua b/busted/block.lua index cc23e546..cb496e26 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -1,3 +1,5 @@ +local getfenv = require 'busted.compatibility'.getfenv +local unpack = require 'busted.compatibility'.unpack local shuffle = require 'busted.utils'.shuffle local function sort(elements) @@ -13,6 +15,81 @@ end return function(busted) local block = {} + function block.reject(descriptor, element) + local env = getfenv(element.run) + if env[descriptor] then + element.env[descriptor] = function(...) + error("'" .. descriptor .. "' not supported inside current context block", 2) + end + end + end + + function block.rejectAll(element) + block.reject('randomize', element) + for descriptor, _ in pairs(busted.executors) do + block.reject(descriptor, element) + end + end + + local function exec(descriptor, element) + if not element.env then element.env = {} end + + block.rejectAll(element) + + local parent = busted.context.parent(element) + setmetatable(element.env, { + __newindex = function(self, key, value) + if not parent.env then parent.env = {} end + parent.env[key] = value + end + }) + + local ret = { busted.safe(descriptor, element.run, element) } + return unpack(ret) + end + + function block.execAll(descriptor, current, propagate, err) + local parent = busted.context.parent(current) + + if propagate and parent then + local success, ancestor = block.execAll(descriptor, parent, propagate) + if not success then + return success, ancestor + end + end + + local list = current[descriptor] or {} + + local success = true + for _, v in pairs(list) do + if not exec(descriptor, v):success() then + if err then err(descriptor) end + success = nil + end + end + return success, current + end + + function block.dexecAll(descriptor, current, propagate, err) + local parent = busted.context.parent(current) + local list = current[descriptor] or {} + + local success = true + for _, v in pairs(list) do + if not exec(descriptor, v):success() then + if err then err(descriptor) end + success = nil + end + end + + if propagate and parent then + if not block.dexecAll(descriptor, parent, propagate) then + success = nil + end + end + return success + end + function block.execute(descriptor, element) if not element.env then element.env = {} end @@ -26,10 +103,10 @@ return function(busted) elseif busted.sort then sort(busted.context.children(element)) end - if busted.execAll('setup', element) then + if block.execAll('setup', element) then busted.execute(element) end - busted.dexecAll('teardown', element) + block.dexecAll('teardown', element) end end diff --git a/busted/core.lua b/busted/core.lua index 3c3545c3..50ec3401 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -234,81 +234,6 @@ return function() busted.export(alias, publisher) end - function busted.reject(descriptor, element) - local env = getfenv(element.run) - if env[descriptor] then - element.env[descriptor] = function(...) - error("'" .. descriptor .. "' not supported inside current context block", 2) - end - end - end - - function busted.rejectAll(element) - busted.reject('randomize', element) - for descriptor, _ in pairs(busted.executors) do - busted.reject(descriptor, element) - end - end - - local function exec(descriptor, element) - if not element.env then element.env = {} end - - busted.rejectAll(element) - - local parent = busted.context.parent(element) - setmetatable(element.env, { - __newindex = function(self, key, value) - if not parent.env then parent.env = {} end - parent.env[key] = value - end - }) - - local ret = { busted.safe(descriptor, element.run, element) } - return unpack(ret) - end - - function busted.execAll(descriptor, current, propagate, err) - local parent = busted.context.parent(current) - - if propagate and parent then - local success, ancestor = busted.execAll(descriptor, parent, propagate) - if not success then - return success, ancestor - end - end - - local list = current[descriptor] or {} - - local success = true - for _, v in pairs(list) do - if not exec(descriptor, v):success() then - if err then err(descriptor) end - success = nil - end - end - return success, current - end - - function busted.dexecAll(descriptor, current, propagate, err) - local parent = busted.context.parent(current) - local list = current[descriptor] or {} - - local success = true - for _, v in pairs(list) do - if not exec(descriptor, v):success() then - if err then err(descriptor) end - success = nil - end - end - - if propagate and parent then - if not busted.dexecAll(descriptor, parent, propagate) then - success = nil - end - end - return success - end - function busted.execute(current) if not current then current = busted.context.get() end for _, v in pairs(busted.context.children(current)) do diff --git a/busted/execute.lua b/busted/execute.lua index dfa5c9fe..17b9d4eb 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -1,5 +1,7 @@ return function(busted) + local block = require 'busted.block'(busted) + local function execute(runs, options) busted.subscribe({'suite', 'reset'}, function() local oldctx = busted.context.get() @@ -30,10 +32,10 @@ return function(busted) local root = busted.context.get() busted.publish({ 'suite', 'start' }, i, runs) - if busted.execAll('setup', root) then + if block.execAll('setup', root) then busted.execute() end - busted.dexecAll('teardown', root) + block.dexecAll('teardown', root) busted.publish({ 'suite', 'end' }, i, runs) if busted.skipAll then diff --git a/busted/init.lua b/busted/init.lua index 90ad16af..e624cfd2 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -21,24 +21,24 @@ local function init(busted) if not element.env then element.env = {} end - busted.rejectAll(element) + block.rejectAll(element) element.env.finally = function(fn) finally = fn end element.env.pending = function(msg) busted.pending(msg) end - local pass, ancestor = busted.execAll('before_each', parent, true) + local pass, ancestor = block.execAll('before_each', parent, true) if pass then local status = busted.status('success') busted.publish({ 'test', 'start' }, element, parent) status:update(busted.safe('it', element.run, element)) if finally then - busted.reject('pending', element) + block.reject('pending', element) status:update(busted.safe('finally', finally, element)) end busted.publish({ 'test', 'end' }, element, parent, tostring(status)) end - busted.dexecAll('after_each', ancestor, true) + block.dexecAll('after_each', ancestor, true) end local pending = function(element) diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 486ca234..01f01691 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -324,6 +324,10 @@ describe('tests aliases', function() end) describe('tests unsupported functions', function() + it('it block does not have file executor', function() + assert.is_nil(file) + end) + it('it block throws error on describe/context', function() assert.has_error(describe, "'describe' not supported inside current context block") assert.has_error(context, "'context' not supported inside current context block") @@ -355,6 +359,8 @@ end) describe('tests unsupported functions in setup/before_each/after_each/teardown', function() local function testUnsupported() + assert.is_nil(file) + assert.is_nil(finally) assert.has_error(randomize, "'randomize' not supported inside current context block") assert.has_error(describe, "'describe' not supported inside current context block") From 467504f27df1ef175e130bd69b3072f66d02fe79 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 6 Mar 2015 16:21:54 -0800 Subject: [PATCH 167/293] Support multiple root paths from CLI This updates the command-line interface to support specifying multiple files/folders instead of just one. --- busted/modules/cli.lua | 16 +++++++++++++++- busted/modules/test_file_loader.lua | 14 +++++++++++--- busted/runner.lua | 4 ++-- spec/modules/cli_spec.lua | 12 +++++++++--- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 88d83c42..4c829c21 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -40,6 +40,13 @@ return function(options) return true end + local function processArgList(key, value) + local list = cliArgsParsed[key] or {} + tablex.insertvalues(list, utils.split(value, ',')) + processArg(key, list) + return true + end + local function processNumber(key, value, altkey, opt) local number = tonumber(value) if not number then @@ -79,7 +86,7 @@ return function(options) cli:add_flag('--version', 'prints the program version and exits', processOption) if options.batch then - cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 1, processArg) + cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 999, processArgList) cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) end @@ -165,6 +172,13 @@ return function(options) cliArgs.Xoutput = fixupList(cliArgs.Xoutput) cliArgs.Xhelper = fixupList(cliArgs.Xhelper) + -- Fix root file paths + if cliArgs.ROOT then + for i, rootFile in ipairs(cliArgs.ROOT) do + cliArgs.ROOT[i] = utils.normpath(path.join(fpath, rootFile)) + end + end + -- We report an error if the same tag appears in both `options.tags` -- and `options.excluded_tags` because it does not make sense for the -- user to tell Busted to include and exclude the same tests at the diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 391cce50..7eb56f60 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -39,6 +39,14 @@ return function(busted, loaders, options) return fileList end + local getAllTestFiles = function(rootFiles, pattern) + local fileList = {} + for _, root in ipairs(rootFiles) do + tablex.insertvalues(fileList, getTestFiles(root, pattern)) + end + return fileList + end + -- runs a testfile, loading its tests local loadTestFile = function(busted, filename) for _, v in pairs(fileLoaders) do @@ -48,8 +56,8 @@ return function(busted, loaders, options) end end - local loadTestFiles = function(rootFile, pattern, loaders) - local fileList = getTestFiles(rootFile, pattern) + local loadTestFiles = function(rootFiles, pattern, loaders) + local fileList = getAllTestFiles(rootFiles, pattern) if options.shuffle then shuffle(fileList, options.seed) @@ -79,6 +87,6 @@ return function(busted, loaders, options) return fileList end - return loadTestFiles, loadTestFile, getTestFiles + return loadTestFiles, loadTestFile, getAllTestFiles end diff --git a/busted/runner.lua b/busted/runner.lua index 7d37257c..b1e77345 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -147,10 +147,10 @@ return function(options) } -- Load test directory - local rootFile = cliArgs.ROOT and utils.normpath(path.join(fpath, cliArgs.ROOT)) or fileName + local rootFiles = cliArgs.ROOT or { fileName } local pattern = cliArgs.pattern local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders, testFileLoaderOptions) - local fileList = testFileLoader(rootFile, pattern) + local fileList = testFileLoader(rootFiles, pattern) if not cliArgs.ROOT then local ctx = busted.context.get() diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 05bb1691..6be21de7 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -9,7 +9,7 @@ describe('Tests command-line interface', function() local args = cli:parse({}) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) - assert.is_equal('spec', args.ROOT) + assert.is_same({'./spec'}, args.ROOT) assert.is_equal('./', args.d) assert.is_equal('./', args.cwd) assert.is_equal('_spec', args.p) @@ -99,11 +99,17 @@ describe('Tests command-line interface', function() it('specify ROOT arg and --pattern', function() local cli = require 'busted.modules.cli'({ batch = true }) local args = cli:parse({ '-p', 'match_files', 'root_is_here' }) - assert.is_equal('root_is_here', args.ROOT) + assert.is_same({'./root_is_here'}, args.ROOT) assert.is_equal('match_files', args.p) assert.is_equal('match_files', args.pattern) end) + it('specify multiple root paths', function() + local cli = require 'busted.modules.cli'({ batch = true }) + local args = cli:parse({'root1_path', 'root2_path', 'root3_path'}) + assert.is_same({'./root1_path', './root2_path', './root3_path'}, args.ROOT) + end) + it('specify --cwd', function() local cli = require 'busted.modules.cli'() local args = cli:parse({ '--cwd=/path/to/dir' }) @@ -190,7 +196,7 @@ describe('Tests using .busted tasks', function() local args = cli:parse({ '--cwd=spec/.hidden' }) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) - assert.is_equal('spec', args.ROOT) + assert.is_same({'spec/.hidden/spec'}, args.ROOT) assert.is_equal('spec/.hidden', args.d) assert.is_equal('spec/.hidden', args.cwd) assert.is_equal('_spec', args.p) From 027ef4d33469a3440f557abfa24685a72e71b0ba Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 6 Mar 2015 16:34:32 -0800 Subject: [PATCH 168/293] Support multiple --cwd options This allows multiple --cwd options to be specified, where each is interpreted relative to the previous one: --cwd=spec --cwd=modules is equivalent to --cwd=spec/modules. --- busted/modules/cli.lua | 8 +++++++- completions/bash/busted.bash | 21 +++++++++++++++++++-- completions/zsh/_busted | 20 +++++++++++++++++--- spec/modules/cli_spec.lua | 14 ++++++++++++++ 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 4c829c21..aea9a51e 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -82,6 +82,12 @@ return function(options) return true end + local function processDir(key, value, altkey, opt) + local dpath = path.join(cliArgsParsed[key] or '', value) + processOption(key, dpath, altkey, opt) + return true + end + -- Load up the command-line interface options cli:add_flag('--version', 'prints the program version and exits', processOption) @@ -92,7 +98,7 @@ return function(options) end cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) - cli:add_option('-d, --cwd=cwd', 'path to current working directory', './', processOption) + cli:add_option('-d, --cwd=cwd', 'path to current working directory. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', nil, processOption) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index bbab5db0..3db7d639 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -45,10 +45,27 @@ _busted() { -r|--run) local d="." local i + local word for (( i=1; i < ${#COMP_WORDS[@]}-1; i++ )); do case "${COMP_WORDS[i]}" in - -d|--cwd) - d="${COMP_WORDS[i+1]}" + -d) + word="${COMP_WORDS[i+1]}" + if [ "${word:0:1}" == "/" ]; then + d="${word}" + else + d="${d}/${word}" + fi + ;; + --cwd) + word="${COMP_WORDS[i+1]}" + if [ "${word}" == "=" ]; then + word="${COMP_WORDS[i+2]}" + fi + if [ "${word:0:1}" == "/" ]; then + d="${word}" + else + d="${d}/${word}" + fi ;; esac done diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 37c33233..449d46ae 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -26,7 +26,7 @@ _busted_args=( "-Xoutput[Pass 'OPTION' as an option to the output handler. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" "-Xhelper[Pass 'OPTION' as an option to the helper script. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" "(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" -"(-d --cwd)"{-d,--cwd=}"[Path to current working directory (default: ./)]:directory:_dirs" +"(-d --cwd)"{-d,--cwd=}"[Path to current working directory. If multiple options are specified, each is interpreted relative to the previous one. (default: ./)]:directory:_dirs" "(-h --help)"{-h,--help}"[Help]" "(-m --lpath)"{-m,--lpath=}"[Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua)]:directory:_dirs" "(-o --output)"{-o,--output=}"[Output library to load (default: utfTerminal)]:output handlers:->output" @@ -50,10 +50,24 @@ case "${state}" in run) local d="." local i - for (( i=1; i < ${#words}-1; i++ )); do + local word + for (( i=1; i < ${#words}; i++ )); do case "${words[i]}" in -d|--cwd) - d="${words[i+1]}" + word="${words[i+1]}" + if [[ "${word[1,1]}" == "/" ]]; then + d="${word}" + else + d="${d}/${word}" + fi + ;; + --cwd=*) + word="${words[i][7,-1]}" + if [[ "${word[1,1]}" == "/" ]]; then + d="${word}" + else + d="${d}/${word}" + fi ;; esac done diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 6be21de7..2a9a4e0f 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -117,6 +117,20 @@ describe('Tests command-line interface', function() assert.is_equal('/path/to/dir', args.cwd) end) + it('specify --cwd multiple times', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--cwd=/path/to', '-d', 'dir', '--cwd=subdir' }) + assert.is_equal('/path/to/dir/subdir', args.d) + assert.is_equal('/path/to/dir/subdir', args.cwd) + end) + + it('specify --cwd multiple times with multiple roots', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--cwd=/path/to', '-d', 'dir', '--cwd=/new/path' }) + assert.is_equal('/new/path', args.d) + assert.is_equal('/new/path', args.cwd) + end) + it('specify --run', function() local cli = require 'busted.modules.cli'() local args = cli:parse({ '--run=task' }) From 91fbc3cdf0fea216b370178ee1a1b61535bee6fa Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 8 Mar 2015 03:41:48 -0700 Subject: [PATCH 169/293] Support multiple --filter and --filter-out options This allows multiple --filter and --filter-out options to be specified on the command-line, where each filter is `OR'ed` with all of the other filters. --- busted/modules/cli.lua | 11 +++++++++-- busted/modules/filter_loader.lua | 16 ++++++++++++---- spec/cl_spec.lua | 6 ++++++ spec/modules/cli_spec.lua | 19 +++++++++++++------ 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index aea9a51e..c28f0924 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -64,6 +64,13 @@ return function(options) return true end + local function processMultiOption(key, value, altkey, opt) + local list = cliArgsParsed[key] or {} + table.insert(list, value) + processOption(key, list, altkey, opt) + return true + end + local function append(s1, s2, sep) local sep = sep or '' if not s1 then return s2 end @@ -101,8 +108,8 @@ return function(options) cli:add_option('-d, --cwd=cwd', 'path to current working directory. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) - cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', nil, processOption) - cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', nil, processOption) + cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', {}, processMultiOption) + cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', {}, processMultiOption) cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processPath) cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processPath) cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) diff --git a/busted/modules/filter_loader.lua b/busted/modules/filter_loader.lua index f6387371..1aaaba0b 100644 --- a/busted/modules/filter_loader.lua +++ b/busted/modules/filter_loader.lua @@ -38,13 +38,21 @@ return function() end local filterOutNames = function(name) - local found = (getFullName(name):find(options.filterOut) ~= nil) - return nil, not found + for _, filter in pairs(options.filterOut) do + if getFullName(name):find(filter) ~= nil then + return nil, false + end + end + return nil, true end local filterNames = function(name) - local found = (getFullName(name):find(options.filter) ~= nil) - return nil, found + for _, filter in pairs(options.filter) do + if getFullName(name):find(filter) ~= nil then + return nil, true + end + end + return nil, (#options.filter == 0) end local printNameOnly = function(name, fn, trace) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 3fea691f..a7920ac6 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -128,6 +128,9 @@ describe('Tests the busted command-line options', function() success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern2"') assert.is_false(success) assert.is_equal(2, exitcode) + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern1" --filter="pattern2"') + assert.is_false(success) + assert.is_equal(4, exitcode) error_end() end) @@ -140,6 +143,9 @@ describe('Tests the busted command-line options', function() success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="pattern%d"') assert.is_false(success) assert.is_equal(5, exitcode) + success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="patt1" --filter-out="patt2"') + assert.is_false(success) + assert.is_equal(3, exitcode) success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="patt.*(%d)"') assert.is_true(success) error_end() diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 2a9a4e0f..c4d067c4 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -39,12 +39,12 @@ describe('Tests command-line interface', function() assert.is_nil(args['sort-files']) assert.is_nil(args.r) assert.is_nil(args.run) - assert.is_nil(args.filter) - assert.is_nil(args['filter-out']) assert.is_nil(args.helper) assert.is_same({}, args.t) assert.is_same({}, args.tags) assert.is_same({}, args['exclude-tags']) + assert.is_same({}, args.filter) + assert.is_same({}, args['filter-out']) assert.is_same({}, args.Xoutput) assert.is_same({}, args.Xhelper) assert.is_same({'lua', 'moonscript'}, args.loaders) @@ -176,8 +176,15 @@ describe('Tests command-line interface', function() it('specify --filter and --filter-out', function() local cli = require 'busted.modules.cli'() local args = cli:parse({ '--filter=_filt', '--filter-out=_filterout' }) - assert.is_equal('_filt', args.filter) - assert.is_equal('_filterout', args['filter-out']) + assert.is_same({'_filt'}, args.filter) + assert.is_same({'_filterout'}, args['filter-out']) + end) + + it('specify --filter and --filter-out multiple times', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--filter=_filt1', '--filter=_filt2', '--filter-out=_filterout1', '--filter-out=_filterout2' }) + assert.is_same({'_filt1', '_filt2'}, args.filter) + assert.is_same({'_filterout1', '_filterout2'}, args['filter-out']) end) it('specify --loaders', function() @@ -240,12 +247,12 @@ describe('Tests using .busted tasks', function() assert.is_nil(args['sort-files']) assert.is_nil(args.r) assert.is_nil(args.run) - assert.is_nil(args.filter) - assert.is_nil(args['filter-out']) assert.is_nil(args.helper) assert.is_same({'tag11', 'tag22', 'tag33'}, args.t) assert.is_same({'tag11', 'tag22', 'tag33'}, args.tags) assert.is_same({'etag11', 'etag22', 'etag33'}, args['exclude-tags']) + assert.is_same({}, args.filter) + assert.is_same({}, args['filter-out']) assert.is_same({'-f', '--flag'}, args.Xoutput) assert.is_same({'-v', '--verbose'}, args.Xhelper) assert.is_same({'terra', 'moonscript'}, args.loaders) From f2667d432d03cb0ff85d0cd6eabd4bf3abea3459 Mon Sep 17 00:00:00 2001 From: mpeterv Date: Tue, 10 Mar 2015 20:29:49 +0300 Subject: [PATCH 170/293] Do not use colors on Windows if ANSICON is not defined --- busted/outputHandlers/utfTerminal.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index cc6d6782..4f2b1c42 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -1,7 +1,15 @@ -local colors = require 'term.colors' local s = require 'say' local pretty = require 'pl.pretty' +local colors + +if package.config:sub(1,1) == '\\' and not os.getenv("ANSICON") then + -- Disable colors on Windows. + colors = setmetatable({}, {__index = function() return function(s) return s end end}) +else + colors = require 'term.colors' +end + return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) From 57314f546647882550ffcf2f911cfa964be98d30 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 14 Mar 2015 00:21:51 -0700 Subject: [PATCH 171/293] Restore arg after loading helper script --- busted/modules/helper_loader.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index 166f7ccd..eb153889 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -3,6 +3,7 @@ local hasMoon, moonscript = pcall(require, 'moonscript') return function() local loadHelper = function(helper, hpath, options, busted) + local old_arg = arg local success, err = pcall(function() arg = options.arguments if helper:match('%.lua$') then @@ -14,6 +15,8 @@ return function() end end) + arg = old_arg + if not success then busted.publish({ 'error', 'helper' }, { descriptor = 'helper', name = helper }, nil, err, {}) end From 1300f5e007cad4057b0bb9748da1db3b4d04b77e Mon Sep 17 00:00:00 2001 From: Zhen Wang Date: Mon, 16 Mar 2015 11:08:17 +0800 Subject: [PATCH 172/293] Arrow output character is not ascii --- busted/outputHandlers/plainTerminal.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 0632558c..d1afefab 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -12,7 +12,7 @@ return function(options, busted) local pendingDescription = function(pending) local name = pending.name - local string = s('output.pending') .. ' → ' .. + local string = s('output.pending') .. ' => ' .. pending.trace.short_src .. ' @ ' .. pending.trace.currentline .. '\n' .. name @@ -40,9 +40,9 @@ return function(options, busted) end local failureDescription = function(failure, isError) - local string = s('output.failure') .. ' → ' + local string = s('output.failure') .. ' => ' if isError then - string = s('output.error') .. ' → ' + string = s('output.error') .. ' => ' end if not failure.element.trace or not failure.element.trace.short_src then From ce08b99757fb085989e488ab1b66c475543ab3b1 Mon Sep 17 00:00:00 2001 From: Nelson Tanquero Date: Mon, 16 Mar 2015 10:59:45 -0400 Subject: [PATCH 173/293] Adding Spanish language for error handling --- busted/languages/es.lua | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 busted/languages/es.lua diff --git a/busted/languages/es.lua b/busted/languages/es.lua new file mode 100644 index 00000000..4219e42e --- /dev/null +++ b/busted/languages/es.lua @@ -0,0 +1,49 @@ +local s = require('say') + +s:set_namespace('es') + +-- 'Pending: test.lua @ 12 \n description +s:set('output.pending', 'Pendiente') +s:set('output.failure', 'Fallo') +s:set('output.error', 'Error') +s:set('output.success', 'Éxito') + +s:set('output.pending_plural', 'pendientes') +s:set('output.failure_plural', 'fallos') +s:set('output.error_plural', 'errores') +s:set('output.success_plural', 'éxitos') + +s:set('output.pending_zero', 'pendientes') +s:set('output.failure_zero', 'fallos') +s:set('output.error_zero', 'errores') +s:set('output.success_zero', 'éxitos') + +s:set('output.pending_single', 'pendiente') +s:set('output.failure_single', 'fallo') +s:set('output.error_single', 'error') +s:set('output.success_single', 'éxito') + +s:set('output.seconds', 'segundos') + +s:set('output.no_test_files_match', 'Ningún fichero de prueba fue encontrado para el patrón de Lua: %s') + +-- definitions following are not used within the 'say' namespace +return { + failure_messages = { + 'Tienes %d especificaciones o pruebas con errores', + 'Tus especificaciones o pruebas están dañadas', + 'Tu código es malo y deberías sentirte mal', + 'Tu código está en la Zona de Peligro', + 'Juego extraño. La única forma de ganar es omitiendo las pruebas', + 'Mi abuela escribió mejores especificaciones en una 386', + 'Cada vez que encuentres un fallo, tómate otra cerveza', + 'Esto no está del todo bien amigo' + }, + success_messages = { + 'Ohhh si! Pasando todas las pruebas', + 'No importa, tenía especificaciones', + 'Esto está bien amigo', + 'Un exitazo', + 'Pasaron las pruebas, tómate otra cerveza', + } +} From a3c3b4e2caf1265c3e0fb50c53133a9083584108 Mon Sep 17 00:00:00 2001 From: Zhen Wang Date: Tue, 17 Mar 2015 10:33:12 +0800 Subject: [PATCH 174/293] Changed double arrow to single arrow --- busted/outputHandlers/plainTerminal.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index d1afefab..c74cb76d 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -12,7 +12,7 @@ return function(options, busted) local pendingDescription = function(pending) local name = pending.name - local string = s('output.pending') .. ' => ' .. + local string = s('output.pending') .. ' -> ' .. pending.trace.short_src .. ' @ ' .. pending.trace.currentline .. '\n' .. name @@ -40,9 +40,9 @@ return function(options, busted) end local failureDescription = function(failure, isError) - local string = s('output.failure') .. ' => ' + local string = s('output.failure') .. ' -> ' if isError then - string = s('output.error') .. ' => ' + string = s('output.error') .. ' -> ' end if not failure.element.trace or not failure.element.trace.short_src then From 68755441b63ffb9d7db98b9bf060adede711a0a3 Mon Sep 17 00:00:00 2001 From: Zhen Wang Date: Tue, 17 Mar 2015 10:36:18 +0800 Subject: [PATCH 175/293] Updated cl_spec for changes to plainTerminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed test to expect "->" instead of "→" --- spec/cl_spec.lua | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index a7920ac6..1b7def4e 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -283,7 +283,7 @@ describe('Tests failing tests through the commandline', function() it('tests failing support functions as errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_failing_support.lua$') - local _, numErrors = result:gsub('Error → .-\n','') + local _, numErrors = result:gsub('Error -> .-\n','') assert.is_equal(9, numErrors) error_end() end) @@ -365,7 +365,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting errors as test errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') - local errmsg = result:match('(Error → .-)\n') + local errmsg = result:match('(Error -> .-)\n') assert.is_truthy(errmsg) error_end() end) @@ -373,7 +373,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting assert failures as test failures', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$') - local failmsg = result:match('(Failure → .-)\n') + local failmsg = result:match('(Failure -> .-)\n') assert.is_truthy(failmsg) error_end() end) @@ -381,7 +381,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting Lua runtime errors as test errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=luaerr') - local failmsg = result:match('(Error → .-)\n') + local failmsg = result:match('(Error -> .-)\n') assert.is_truthy(failmsg) error_end() end) @@ -426,9 +426,9 @@ describe('Tests error messages through the command line', function() it('when throwing errors in a test', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') - local err = result:match('(Error → .-)\n') + local err = result:match('(Error -> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error → ./spec/cl_errors.lua @ 5" + local expectedErr = "Error -> ./spec/cl_errors.lua @ 5" local expectedMsg = "./spec/cl_errors.lua:6: force an error" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -474,8 +474,8 @@ describe('Tests error messages through the command line', function() it('when running a non-compiling testfile', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_compile_fail.lua$') - local errmsg = result:match('(Error → .-:%d+:) ') - local expected = "Error → ./spec/cl_compile_fail.lua:3:" + local errmsg = result:match('(Error -> .-:%d+:) ') + local expected = "Error -> ./spec/cl_compile_fail.lua:3:" assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -483,9 +483,9 @@ describe('Tests error messages through the command line', function() it('when a testfile throws errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_execute_fail.lua$') - local err = result:match('(Error → .-)\n') + local err = result:match('(Error -> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\]cl_execute_fail%.lua:%d+:.-)\n') - local expectedErr = 'Error → ./spec/cl_execute_fail.lua @ 4' + local expectedErr = 'Error -> ./spec/cl_execute_fail.lua @ 4' local expectedMsg = './spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -504,7 +504,7 @@ describe('Tests error messages through the command line', function() it('when helper script not found', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here') - local err = result:match('Error → .-:%d+: (.-)\n') + local err = result:match('Error -> .-:%d+: (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = "module 'not_found_here' not found:" local expectedMsg = 'Error: Cannot load helper script: not_found_here' @@ -516,7 +516,7 @@ describe('Tests error messages through the command line', function() it('when helper lua script not found', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua') - local err = result:match('Error → (.-)\n') + local err = result:match('Error -> (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = 'cannot open ./not_found_here.lua: No such file or directory' local expectedMsg = 'Error: Cannot load helper script: not_found_here.lua' @@ -528,7 +528,7 @@ describe('Tests error messages through the command line', function() it('when no test files matching Lua pattern', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') - local errmsg = result:match('Error → (.-)\n') + local errmsg = result:match('Error -> (.-)\n') local expected = 'No test files found matching Lua pattern: this_filename_does_simply_not_exist$' assert.is_equal(expected, errmsg) error_end() @@ -539,9 +539,9 @@ describe('Tests moonscript error messages through the command line', function() it('when assertion fails', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') - local err = result:match('(Failure → .-)\n') + local err = result:match('(Failure -> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Failure → ./spec/cl_moonscript_error_messages.moon @ 4" + local expectedErr = "Failure -> ./spec/cl_moonscript_error_messages.moon @ 4" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -551,9 +551,9 @@ describe('Tests moonscript error messages through the command line', function() it('when throwing string errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') - local err = result:match('(Error → .-)\n') + local err = result:match('(Error -> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error → ./spec/cl_moonscript_error_messages.moon @ 16" + local expectedErr = "Error -> ./spec/cl_moonscript_error_messages.moon @ 16" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:17: error message" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -594,7 +594,7 @@ describe('Tests pending through the commandline', function() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') - local _, numPending = result:gsub('Pending → .-\n', '') + local _, numPending = result:gsub('Pending -> .-\n', '') assert.is_equal(2, pendingDots) assert.is_equal(2, numPending) error_end() @@ -605,7 +605,7 @@ describe('Tests pending through the commandline', function() local result = run(busted_cmd .. ' --output=plainTerminal --suppress-pending --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') - local _, numPending = result:gsub('Pending → .-\n', '') + local _, numPending = result:gsub('Pending -> .-\n', '') assert.is_equal(0, pendingDots) assert.is_equal(0, numPending) error_end() From 3c3fb94ce0924c0bd7eeaaf02af8b6ab32372fd7 Mon Sep 17 00:00:00 2001 From: Zhen Wang Date: Tue, 17 Mar 2015 11:02:37 +0800 Subject: [PATCH 176/293] Updated cl_spec for changes to plainTerminal Need to escape "-" --- spec/cl_spec.lua | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 1b7def4e..71ee1b30 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -283,7 +283,7 @@ describe('Tests failing tests through the commandline', function() it('tests failing support functions as errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_failing_support.lua$') - local _, numErrors = result:gsub('Error -> .-\n','') + local _, numErrors = result:gsub('Error %-> .-\n','') assert.is_equal(9, numErrors) error_end() end) @@ -365,7 +365,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting errors as test errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') - local errmsg = result:match('(Error -> .-)\n') + local errmsg = result:match('(Error %-> .-)\n') assert.is_truthy(errmsg) error_end() end) @@ -373,7 +373,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting assert failures as test failures', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$') - local failmsg = result:match('(Failure -> .-)\n') + local failmsg = result:match('(Failure %-> .-)\n') assert.is_truthy(failmsg) error_end() end) @@ -381,7 +381,7 @@ describe('Tests distinguish between errors and failures', function() it('by detecting Lua runtime errors as test errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=luaerr') - local failmsg = result:match('(Error -> .-)\n') + local failmsg = result:match('(Error %-> .-)\n') assert.is_truthy(failmsg) error_end() end) @@ -426,9 +426,9 @@ describe('Tests error messages through the command line', function() it('when throwing errors in a test', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') - local err = result:match('(Error -> .-)\n') + local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error -> ./spec/cl_errors.lua @ 5" + local expectedErr = "Error %-> ./spec/cl_errors.lua @ 5" local expectedMsg = "./spec/cl_errors.lua:6: force an error" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -474,8 +474,8 @@ describe('Tests error messages through the command line', function() it('when running a non-compiling testfile', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_compile_fail.lua$') - local errmsg = result:match('(Error -> .-:%d+:) ') - local expected = "Error -> ./spec/cl_compile_fail.lua:3:" + local errmsg = result:match('(Error %-> .-:%d+:) ') + local expected = "Error %-> ./spec/cl_compile_fail.lua:3:" assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -483,9 +483,9 @@ describe('Tests error messages through the command line', function() it('when a testfile throws errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_execute_fail.lua$') - local err = result:match('(Error -> .-)\n') + local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\]cl_execute_fail%.lua:%d+:.-)\n') - local expectedErr = 'Error -> ./spec/cl_execute_fail.lua @ 4' + local expectedErr = 'Error %-> ./spec/cl_execute_fail.lua @ 4' local expectedMsg = './spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -504,7 +504,7 @@ describe('Tests error messages through the command line', function() it('when helper script not found', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here') - local err = result:match('Error -> .-:%d+: (.-)\n') + local err = result:match('Error %-> .-:%d+: (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = "module 'not_found_here' not found:" local expectedMsg = 'Error: Cannot load helper script: not_found_here' @@ -516,7 +516,7 @@ describe('Tests error messages through the command line', function() it('when helper lua script not found', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua') - local err = result:match('Error -> (.-)\n') + local err = result:match('Error %-> (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = 'cannot open ./not_found_here.lua: No such file or directory' local expectedMsg = 'Error: Cannot load helper script: not_found_here.lua' @@ -528,7 +528,7 @@ describe('Tests error messages through the command line', function() it('when no test files matching Lua pattern', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') - local errmsg = result:match('Error -> (.-)\n') + local errmsg = result:match('Error %-> (.-)\n') local expected = 'No test files found matching Lua pattern: this_filename_does_simply_not_exist$' assert.is_equal(expected, errmsg) error_end() @@ -539,9 +539,9 @@ describe('Tests moonscript error messages through the command line', function() it('when assertion fails', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') - local err = result:match('(Failure -> .-)\n') + local err = result:match('(Failure %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Failure -> ./spec/cl_moonscript_error_messages.moon @ 4" + local expectedErr = "Failure %-> ./spec/cl_moonscript_error_messages.moon @ 4" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -551,9 +551,9 @@ describe('Tests moonscript error messages through the command line', function() it('when throwing string errors', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') - local err = result:match('(Error -> .-)\n') + local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error -> ./spec/cl_moonscript_error_messages.moon @ 16" + local expectedErr = "Error %-> ./spec/cl_moonscript_error_messages.moon @ 16" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:17: error message" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -594,7 +594,7 @@ describe('Tests pending through the commandline', function() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') - local _, numPending = result:gsub('Pending -> .-\n', '') + local _, numPending = result:gsub('Pending %-> .-\n', '') assert.is_equal(2, pendingDots) assert.is_equal(2, numPending) error_end() @@ -605,7 +605,7 @@ describe('Tests pending through the commandline', function() local result = run(busted_cmd .. ' --output=plainTerminal --suppress-pending --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') - local _, numPending = result:gsub('Pending -> .-\n', '') + local _, numPending = result:gsub('Pending %-> .-\n', '') assert.is_equal(0, pendingDots) assert.is_equal(0, numPending) error_end() From 470862af978a93f805a137dff79388a657e1d6ad Mon Sep 17 00:00:00 2001 From: Zhen Wang Date: Tue, 17 Mar 2015 11:09:21 +0800 Subject: [PATCH 177/293] Updated cl_spec for changes to plainTerminal Accidentally added escape to non-regex comparison --- spec/cl_spec.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 71ee1b30..9001d439 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -428,7 +428,7 @@ describe('Tests error messages through the command line', function() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error %-> ./spec/cl_errors.lua @ 5" + local expectedErr = "Error -> ./spec/cl_errors.lua @ 5" local expectedMsg = "./spec/cl_errors.lua:6: force an error" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -475,7 +475,7 @@ describe('Tests error messages through the command line', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_compile_fail.lua$') local errmsg = result:match('(Error %-> .-:%d+:) ') - local expected = "Error %-> ./spec/cl_compile_fail.lua:3:" + local expected = "Error -> ./spec/cl_compile_fail.lua:3:" assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -485,7 +485,7 @@ describe('Tests error messages through the command line', function() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_execute_fail.lua$') local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\]cl_execute_fail%.lua:%d+:.-)\n') - local expectedErr = 'Error %-> ./spec/cl_execute_fail.lua @ 4' + local expectedErr = 'Error -> ./spec/cl_execute_fail.lua @ 4' local expectedMsg = './spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -541,7 +541,7 @@ describe('Tests moonscript error messages through the command line', function() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') local err = result:match('(Failure %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Failure %-> ./spec/cl_moonscript_error_messages.moon @ 4" + local expectedErr = "Failure -> ./spec/cl_moonscript_error_messages.moon @ 4" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) @@ -553,7 +553,7 @@ describe('Tests moonscript error messages through the command line', function() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error %-> ./spec/cl_moonscript_error_messages.moon @ 16" + local expectedErr = "Error -> ./spec/cl_moonscript_error_messages.moon @ 16" local expectedMsg = "./spec/cl_moonscript_error_messages.moon:17: error message" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) From 5d8ebebad636e76d01643dc0538882d77364d571 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 15 Mar 2015 02:13:38 -0700 Subject: [PATCH 178/293] Refactor current working directory Rename refactor -d, --cwd options to -C, --directory, and update option to change to the specified directory before running any tests or doing anything else. This is consistent with other commands like make and tar. --- busted/modules/cli.lua | 29 +--------- busted/modules/helper_loader.lua | 6 +- busted/modules/output_handler_loader.lua | 6 +- busted/runner.lua | 12 ++-- completions/bash/busted.bash | 8 +-- completions/zsh/_busted | 6 +- spec/cl_spec.lua | 70 ++++++++++++------------ spec/modules/cli_spec.lua | 62 ++++++++++----------- 8 files changed, 88 insertions(+), 111 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index c28f0924..0c0d6ea3 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -105,7 +105,7 @@ return function(options) end cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) - cli:add_option('-d, --cwd=cwd', 'path to current working directory. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) + cli:add_option('-C, --directory=DIR', 'change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', {}, processMultiOption) @@ -146,7 +146,7 @@ return function(options) -- Load busted config file if available local configFile = { } - local bustedConfigFilePath = utils.normpath(path.join(cliArgs.cwd, '.busted')) + local bustedConfigFilePath = utils.normpath(path.join(cliArgs.directory, '.busted')) local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) if bustedConfigFile then local config, err = configLoader(configFile, cliArgsParsed, cliArgs) @@ -159,24 +159,6 @@ return function(options) cliArgs = tablex.merge(cliArgs, cliArgsParsed, true) end - local fpath = utils.normpath(cliArgs.cwd):gsub('[/%\\]$', '') - - -- Add additional package paths based on lpath and cpath cliArgs - if #cliArgs.lpath > 0 then - local lpath = cliArgs.lpath - lpath = lpath:gsub('^%.([/%\\])', fpath .. '%1') - lpath = lpath:gsub(';%.([/%\\])', ';' .. fpath .. '%1') - cliArgs.lpath = lpath - cliArgs.m = lpath - end - - if #cliArgs.cpath > 0 then - local cpath = cliArgs.cpath - cpath = cpath:gsub('^%.([/%\\])', fpath .. '%1') - cpath = cpath:gsub(';%.([/%\\])', ';' .. fpath .. '%1') - cliArgs.cpath = cpath - end - -- Fixup options in case options from config file are not of the right form cliArgs.tags = fixupList(cliArgs.tags) cliArgs.t = cliArgs.tags @@ -185,13 +167,6 @@ return function(options) cliArgs.Xoutput = fixupList(cliArgs.Xoutput) cliArgs.Xhelper = fixupList(cliArgs.Xhelper) - -- Fix root file paths - if cliArgs.ROOT then - for i, rootFile in ipairs(cliArgs.ROOT) do - cliArgs.ROOT[i] = utils.normpath(path.join(fpath, rootFile)) - end - end - -- We report an error if the same tag appears in both `options.tags` -- and `options.excluded_tags` because it does not make sense for the -- user to tell Busted to include and exclude the same tests at the diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index eb153889..1559abe1 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -2,14 +2,14 @@ local utils = require 'busted.utils' local hasMoon, moonscript = pcall(require, 'moonscript') return function() - local loadHelper = function(helper, hpath, options, busted) + local loadHelper = function(helper, options, busted) local old_arg = arg local success, err = pcall(function() arg = options.arguments if helper:match('%.lua$') then - dofile(utils.normpath(hpath)) + dofile(utils.normpath(helper)) elseif hasMoon and helper:match('%.moon$') then - moonscript.dofile(utils.normpath(hpath)) + moonscript.dofile(utils.normpath(helper)) else require(helper) end diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index d5221184..71f244f5 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -2,14 +2,14 @@ local utils = require 'busted.utils' local hasMoon, moonscript = pcall(require, 'moonscript') return function() - local loadOutputHandler = function(output, opath, options, busted, defaultOutput) + local loadOutputHandler = function(output, options, busted, defaultOutput) local handler local success, err = pcall(function() if output:match('%.lua$') then - handler = dofile(utils.normpath(opath)) + handler = dofile(utils.normpath(output)) elseif hasMoon and output:match('%.moon$') then - handler = moonscript.dofile(utils.normpath(opath)) + handler = moonscript.dofile(utils.normpath(output)) else handler = require('busted.outputHandlers.' .. output) end diff --git a/busted/runner.lua b/busted/runner.lua index b1e77345..1fa1f1d0 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -43,7 +43,11 @@ return function(options) end -- Load current working directory - local fpath = utils.normpath(cliArgs.cwd) + local _, err = path.chdir(utils.normpath(cliArgs.directory)) + if err then + print('Error: ' .. err) + osexit(1, true) + end -- If coverage arg is passed in, load LuaCovsupport if cliArgs.coverage then @@ -99,8 +103,7 @@ return function(options) arguments = cliArgs.Xoutput } - local opath = utils.normpath(path.join(fpath, cliArgs.output)) - local outputHandler = outputHandlerLoader(cliArgs.output, opath, outputHandlerOptions, busted, options.defaultOutput) + local outputHandler = outputHandlerLoader(cliArgs.output, outputHandlerOptions, busted, options.defaultOutput) outputHandler:subscribe(outputHandlerOptions) if cliArgs['enable-sound'] then @@ -133,8 +136,7 @@ return function(options) arguments = cliArgs.Xhelper } - local hpath = utils.normpath(path.join(fpath, cliArgs.helper)) - helperLoader(cliArgs.helper, hpath, helperOptions, busted) + helperLoader(cliArgs.helper, helperOptions, busted) end -- Set up test loader options diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 3db7d639..6c3f1956 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -48,7 +48,7 @@ _busted() { local word for (( i=1; i < ${#COMP_WORDS[@]}-1; i++ )); do case "${COMP_WORDS[i]}" in - -d) + -C) word="${COMP_WORDS[i+1]}" if [ "${word:0:1}" == "/" ]; then d="${word}" @@ -56,7 +56,7 @@ _busted() { d="${d}/${word}" fi ;; - --cwd) + --directory) word="${COMP_WORDS[i+1]}" if [ "${word}" == "=" ]; then word="${COMP_WORDS[i+2]}" @@ -94,7 +94,7 @@ _busted() { COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" ) return 0 ;; - -d|--cwd) + -C|--directory) _filedir -d return 0 ;; @@ -140,7 +140,7 @@ _busted() { -l --list -o --output= -p --pattern= - -d --cwd= + -C --Cwd= -t --tags= --exclude-tags= -m --lpath= --cpath= -r --run= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 449d46ae..87dd3c97 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -26,7 +26,7 @@ _busted_args=( "-Xoutput[Pass 'OPTION' as an option to the output handler. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" "-Xhelper[Pass 'OPTION' as an option to the helper script. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" "(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" -"(-d --cwd)"{-d,--cwd=}"[Path to current working directory. If multiple options are specified, each is interpreted relative to the previous one. (default: ./)]:directory:_dirs" +"(-C --directory)"{-C,--directory=}"[Change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one. (default: ./)]:directory:_dirs" "(-h --help)"{-h,--help}"[Help]" "(-m --lpath)"{-m,--lpath=}"[Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua)]:directory:_dirs" "(-o --output)"{-o,--output=}"[Output library to load (default: utfTerminal)]:output handlers:->output" @@ -53,7 +53,7 @@ case "${state}" in local word for (( i=1; i < ${#words}; i++ )); do case "${words[i]}" in - -d|--cwd) + -C|--directory) word="${words[i+1]}" if [[ "${word[1,1]}" == "/" ]]; then d="${word}" @@ -61,7 +61,7 @@ case "${state}" in d="${d}/${word}" fi ;; - --cwd=*) + --directory=*) word="${words[i][7,-1]}" if [[ "${word[1,1]}" == "/" ]]; then d="${word}" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 9001d439..5e33fd56 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -173,17 +173,17 @@ describe('Tests the busted command-line options', function() it('tests running with -l specified', function() local result = run(busted_cmd .. ' -l --pattern=cl_list.lua$') - local expected = './spec/cl_list.lua:4: Tests list test 1\n' .. - './spec/cl_list.lua:7: Tests list test 2\n' .. - './spec/cl_list.lua:10: Tests list test 3\n' + local expected = 'spec/cl_list.lua:4: Tests list test 1\n' .. + 'spec/cl_list.lua:7: Tests list test 2\n' .. + 'spec/cl_list.lua:10: Tests list test 3\n' assert.is_equal(normpath(expected), result) end) it('tests running with --list specified', function() local result = run(busted_cmd .. ' --list --pattern=cl_list.lua$') - local expected = './spec/cl_list.lua:4: Tests list test 1\n' .. - './spec/cl_list.lua:7: Tests list test 2\n' .. - './spec/cl_list.lua:10: Tests list test 3\n' + local expected = 'spec/cl_list.lua:4: Tests list test 1\n' .. + 'spec/cl_list.lua:7: Tests list test 2\n' .. + 'spec/cl_list.lua:10: Tests list test 3\n' assert.is_equal(normpath(expected), result) end) @@ -393,7 +393,7 @@ describe('Tests stack trackback', function() local result = run(busted_cmd .. ' --verbose --pattern=cl_errors.lua$ --tags=testerr') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: - ./spec/cl_errors.lua:6: in function <./spec/cl_errors.lua:5> + spec/cl_errors.lua:6: in function ]] assert.is_equal(normpath(expected), errmsg) error_end() @@ -404,7 +404,7 @@ describe('Tests stack trackback', function() local result = run(busted_cmd .. ' --verbose --pattern=cl_two_failures.lua$ --tags=err1') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: - ./spec/cl_two_failures.lua:6: in function <./spec/cl_two_failures.lua:5> + spec/cl_two_failures.lua:6: in function ]] assert.is_equal(normpath(expected), errmsg) error_end() @@ -415,7 +415,7 @@ describe('Tests stack trackback', function() local result = run(busted_cmd .. ' --verbose --pattern=cl_errors.lua$ --tags=luaerr') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: - ./spec/cl_errors.lua:11: in function <./spec/cl_errors.lua:9> + spec/cl_errors.lua:11: in function ]] assert.is_equal(normpath(expected), errmsg) error_end() @@ -427,9 +427,9 @@ describe('Tests error messages through the command line', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') local err = result:match('(Error %-> .-)\n') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error -> ./spec/cl_errors.lua @ 5" - local expectedMsg = "./spec/cl_errors.lua:6: force an error" + local errmsg = result:match('\n(spec[/\\].-)\n') + local expectedErr = "Error -> spec/cl_errors.lua @ 5" + local expectedMsg = "spec/cl_errors.lua:6: force an error" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) error_end() @@ -438,8 +438,8 @@ describe('Tests error messages through the command line', function() it('when throwing an error table', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --tags=table --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expected = './spec/cl_error_messages.lua:5: {' + local errmsg = result:match('\n(spec[/\\].-)\n') + local expected = 'spec/cl_error_messages.lua:5: {' assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -447,8 +447,8 @@ describe('Tests error messages through the command line', function() it('when throwing a nil error', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --tags=nil --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expected = './spec/cl_error_messages.lua:9: Nil error' + local errmsg = result:match('\n(spec[/\\].-)\n') + local expected = 'spec/cl_error_messages.lua:9: Nil error' assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -456,8 +456,8 @@ describe('Tests error messages through the command line', function() it('when throwing an error table with __tostring', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --tags=tostring --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expected = './spec/cl_error_messages.lua:17: {}' + local errmsg = result:match('\n(spec[/\\].-)\n') + local expected = 'spec/cl_error_messages.lua:17: {}' assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -465,8 +465,8 @@ describe('Tests error messages through the command line', function() it('when throwing after a pcall', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --tags=pcall --pattern=cl_error_messages.lua$') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expected = './spec/cl_error_messages.lua:22: error after pcall' + local errmsg = result:match('\n(spec[/\\].-)\n') + local expected = 'spec/cl_error_messages.lua:22: error after pcall' assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -475,7 +475,7 @@ describe('Tests error messages through the command line', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_compile_fail.lua$') local errmsg = result:match('(Error %-> .-:%d+:) ') - local expected = "Error -> ./spec/cl_compile_fail.lua:3:" + local expected = "Error -> spec/cl_compile_fail.lua:3:" assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -484,9 +484,9 @@ describe('Tests error messages through the command line', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_execute_fail.lua$') local err = result:match('(Error %-> .-)\n') - local errmsg = result:match('\n(%.[/\\]spec[/\\]cl_execute_fail%.lua:%d+:.-)\n') - local expectedErr = 'Error -> ./spec/cl_execute_fail.lua @ 4' - local expectedMsg = './spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' + local errmsg = result:match('\n(spec[/\\]cl_execute_fail%.lua:%d+:.-)\n') + local expectedErr = 'Error -> spec/cl_execute_fail.lua @ 4' + local expectedMsg = 'spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) error_end() @@ -518,7 +518,7 @@ describe('Tests error messages through the command line', function() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua') local err = result:match('Error %-> (.-)\n') local errmsg = result:match('(.-)\n') - local expectedErr = 'cannot open ./not_found_here.lua: No such file or directory' + local expectedErr = 'cannot open not_found_here.lua: No such file or directory' local expectedMsg = 'Error: Cannot load helper script: not_found_here.lua' assert.is_equal(normpath(expectedErr), err) assert.is_equal(expectedMsg, errmsg) @@ -540,9 +540,9 @@ describe('Tests moonscript error messages through the command line', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') local err = result:match('(Failure %-> .-)\n') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Failure -> ./spec/cl_moonscript_error_messages.moon @ 4" - local expectedMsg = "./spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." + local errmsg = result:match('\n(spec[/\\].-)\n') + local expectedErr = "Failure -> spec/cl_moonscript_error_messages.moon @ 4" + local expectedMsg = "spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) error_end() @@ -552,9 +552,9 @@ describe('Tests moonscript error messages through the command line', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') local err = result:match('(Error %-> .-)\n') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expectedErr = "Error -> ./spec/cl_moonscript_error_messages.moon @ 16" - local expectedMsg = "./spec/cl_moonscript_error_messages.moon:17: error message" + local errmsg = result:match('\n(spec[/\\].-)\n') + local expectedErr = "Error -> spec/cl_moonscript_error_messages.moon @ 16" + local expectedMsg = "spec/cl_moonscript_error_messages.moon:17: error message" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) error_end() @@ -563,8 +563,8 @@ describe('Tests moonscript error messages through the command line', function() it('when throwing an error table', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --tags=table --pattern=cl_moonscript_error_messages.moon$') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expected = './spec/cl_moonscript_error_messages.moon:9: {' + local errmsg = result:match('\n(spec[/\\].-)\n') + local expected = 'spec/cl_moonscript_error_messages.moon:9: {' assert.is_equal(normpath(expected), errmsg) error_end() end) @@ -572,8 +572,8 @@ describe('Tests moonscript error messages through the command line', function() it('when throwing a nil error', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --tags=nil --pattern=cl_moonscript_error_messages.moon$') - local errmsg = result:match('\n(%.[/\\]spec[/\\].-)\n') - local expected = './spec/cl_moonscript_error_messages.moon:13: Nil error' + local errmsg = result:match('\n(spec[/\\].-)\n') + local expected = 'spec/cl_moonscript_error_messages.moon:13: Nil error' assert.is_equal(normpath(expected), errmsg) error_end() end) diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index c4d067c4..e845792c 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -9,9 +9,9 @@ describe('Tests command-line interface', function() local args = cli:parse({}) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) - assert.is_same({'./spec'}, args.ROOT) - assert.is_equal('./', args.d) - assert.is_equal('./', args.cwd) + assert.is_same({'spec'}, args.ROOT) + assert.is_equal('./', args.C) + assert.is_equal('./', args.directory) assert.is_equal('_spec', args.p) assert.is_equal('_spec', args.pattern) assert.is_equal('os.time()', args.seed) @@ -99,7 +99,7 @@ describe('Tests command-line interface', function() it('specify ROOT arg and --pattern', function() local cli = require 'busted.modules.cli'({ batch = true }) local args = cli:parse({ '-p', 'match_files', 'root_is_here' }) - assert.is_same({'./root_is_here'}, args.ROOT) + assert.is_same({'root_is_here'}, args.ROOT) assert.is_equal('match_files', args.p) assert.is_equal('match_files', args.pattern) end) @@ -107,28 +107,28 @@ describe('Tests command-line interface', function() it('specify multiple root paths', function() local cli = require 'busted.modules.cli'({ batch = true }) local args = cli:parse({'root1_path', 'root2_path', 'root3_path'}) - assert.is_same({'./root1_path', './root2_path', './root3_path'}, args.ROOT) + assert.is_same({'root1_path', 'root2_path', 'root3_path'}, args.ROOT) end) - it('specify --cwd', function() + it('specify --directory', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '--cwd=/path/to/dir' }) - assert.is_equal('/path/to/dir', args.d) - assert.is_equal('/path/to/dir', args.cwd) + local args = cli:parse({ '--directory=/path/to/dir' }) + assert.is_equal('/path/to/dir', args.C) + assert.is_equal('/path/to/dir', args.directory) end) - it('specify --cwd multiple times', function() + it('specify --directory multiple times', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '--cwd=/path/to', '-d', 'dir', '--cwd=subdir' }) - assert.is_equal('/path/to/dir/subdir', args.d) - assert.is_equal('/path/to/dir/subdir', args.cwd) + local args = cli:parse({ '--directory=/path/to', '-C', 'dir', '--directory=subdir' }) + assert.is_equal('/path/to/dir/subdir', args.C) + assert.is_equal('/path/to/dir/subdir', args.directory) end) - it('specify --cwd multiple times with multiple roots', function() + it('specify --directory multiple times with multiple roots', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '--cwd=/path/to', '-d', 'dir', '--cwd=/new/path' }) - assert.is_equal('/new/path', args.d) - assert.is_equal('/new/path', args.cwd) + local args = cli:parse({ '--directory=/path/to', '-C', 'dir', '--directory=/new/path' }) + assert.is_equal('/new/path', args.C) + assert.is_equal('/new/path', args.directory) end) it('specify --run', function() @@ -195,31 +195,31 @@ describe('Tests command-line interface', function() it('specify --lpath', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '-d', '/root', '--lpath=./path1/?.lua', '-m', './path2/?.lua' }) - assert.is_equal('/root/path1/?.lua;/root/path2/?.lua', args.m) - assert.is_equal('/root/path1/?.lua;/root/path2/?.lua', args.lpath) + local args = cli:parse({ '-C', '/root', '--lpath=./path1/?.lua', '-m', './path2/?.lua' }) + assert.is_equal('./path1/?.lua;./path2/?.lua', args.m) + assert.is_equal('./path1/?.lua;./path2/?.lua', args.lpath) end) it('specify --cpath', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '-d', '/croot', '--lpath=./path1/?.so', '-m', './path2/?.so' }) - assert.is_equal('/croot/path1/?.so;/croot/path2/?.so', args.m) - assert.is_equal('/croot/path1/?.so;/croot/path2/?.so', args.lpath) + local args = cli:parse({ '-C', '/croot', '--lpath=./path1/?.so', '-m', './path2/?.so' }) + assert.is_equal('./path1/?.so;./path2/?.so', args.m) + assert.is_equal('./path1/?.so;./path2/?.so', args.lpath) end) end) describe('Tests using .busted tasks', function() it('default options', function() local defaultOutput = 'default_output_handler' - local lpath = 'spec/.hidden/src/?.lua;spec/.hidden/src/?/?.lua;spec/.hidden/src/?/init.lua' - local cpath = path.is_windows and 'spec/.hidden/csrc/?.dll;spec/.hidden/csrc/?/?.dll;' or 'spec/.hidden/csrc/?.so;spec/.hidden/csrc/?/?.so;' + local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' + local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) - local args = cli:parse({ '--cwd=spec/.hidden' }) + local args = cli:parse({ '--directory=spec/.hidden' }) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) - assert.is_same({'spec/.hidden/spec'}, args.ROOT) - assert.is_equal('spec/.hidden', args.d) - assert.is_equal('spec/.hidden', args.cwd) + assert.is_same({'spec'}, args.ROOT) + assert.is_equal('spec/.hidden', args.C) + assert.is_equal('spec/.hidden', args.directory) assert.is_equal('_spec', args.p) assert.is_equal('_spec%.lua$', args.pattern) assert.is_equal('os.time()', args.seed) @@ -260,7 +260,7 @@ describe('Tests using .busted tasks', function() it('load configuration options', function() local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) - local args = cli:parse({ '--cwd=spec/.hidden', '--run=test' }) + local args = cli:parse({ '--directory=spec/.hidden', '--run=test' }) assert.is_equal('_test%.lua$', args.pattern) assert.is_same({'test1', 'test2', 'test3'}, args.tags) assert.is_same({'etest1', 'etest2', 'etest3'}, args['exclude-tags']) @@ -271,7 +271,7 @@ describe('Tests using .busted tasks', function() it('load configuration options and override with command-line', function() local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) - local args = cli:parse({ '--cwd=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--loaders=moonscript' }) + local args = cli:parse({ '--directory=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--loaders=moonscript' }) assert.is_equal('patt', args.pattern) assert.is_same({'tag1'}, args.tags) assert.is_same({'etest1', 'etest2', 'etest3'}, args['exclude-tags']) From 6e32b391052f618521e05d48aaf594352f63190f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 15 Mar 2015 02:28:04 -0700 Subject: [PATCH 179/293] Refactor error messages Send error messages to stderr and prefix error messages with app name. --- busted/runner.lua | 11 ++++++----- spec/cl_spec.lua | 12 ++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/busted/runner.lua b/busted/runner.lua index 1fa1f1d0..c1f0bf5d 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -29,10 +29,11 @@ return function(options) local fileName = source:sub(1,1) == '@' and source:sub(2) or source -- Parse the cli arguments - cli:set_name(path.basename(fileName)) + local appName = path.basename(fileName) + cli:set_name(appName) local cliArgs, err = cli:parse(arg) if not cliArgs then - print(err) + io.stderr:write(err .. '\n') osexit(1, true) end @@ -45,7 +46,7 @@ return function(options) -- Load current working directory local _, err = path.chdir(utils.normpath(cliArgs.directory)) if err then - print('Error: ' .. err) + io.stderr:write(appName .. ': error: ' .. err .. '\n') osexit(1, true) end @@ -69,12 +70,12 @@ return function(options) local quitOnError = cliArgs['no-keep-going'] busted.subscribe({ 'error', 'output' }, function(element, parent, message) - print('Error: Cannot load output library: ' .. element.name .. '\n' .. message) + io.stderr:write(appName .. ': error: Cannot load output library: ' .. element.name .. '\n' .. message .. '\n') return nil, true end) busted.subscribe({ 'error', 'helper' }, function(element, parent, message) - print('Error: Cannot load helper script: ' .. element.name .. '\n' .. message) + io.stderr:write(appName .. ': error: Cannot load helper script: ' .. element.name .. '\n' .. message .. '\n') return nil, true end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 5e33fd56..e7c7f665 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -494,20 +494,20 @@ describe('Tests error messages through the command line', function() it('when output library not found', function() error_start() - local result = run(busted_cmd .. ' --pattern=cl_two_failures.lua$ --output=not_found_here') + local result = run(busted_cmd .. ' --pattern=cl_two_failures.lua$ --output=not_found_here 2>&1') local errmsg = result:match('(.-)\n') - local expected = 'Error: Cannot load output library: not_found_here' + local expected = 'busted: error: Cannot load output library: not_found_here' assert.is_equal(expected, errmsg) error_end() end) it('when helper script not found', function() error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here 2>&1') local err = result:match('Error %-> .-:%d+: (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = "module 'not_found_here' not found:" - local expectedMsg = 'Error: Cannot load helper script: not_found_here' + local expectedMsg = 'busted: error: Cannot load helper script: not_found_here' assert.is_equal(expectedErr, err) assert.is_equal(expectedMsg, errmsg) error_end() @@ -515,11 +515,11 @@ describe('Tests error messages through the command line', function() it('when helper lua script not found', function() error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua') + local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua 2>&1') local err = result:match('Error %-> (.-)\n') local errmsg = result:match('(.-)\n') local expectedErr = 'cannot open not_found_here.lua: No such file or directory' - local expectedMsg = 'Error: Cannot load helper script: not_found_here.lua' + local expectedMsg = 'busted: error: Cannot load helper script: not_found_here.lua' assert.is_equal(normpath(expectedErr), err) assert.is_equal(expectedMsg, errmsg) error_end() From fc26ce6031c3b2ac962749c2d9266ba59c028e0a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 14 Mar 2015 20:54:01 -0700 Subject: [PATCH 180/293] Support both strict and lazy setup/teardown This allows strict or lazy setup/teardown functions to be used explicitly, rather than defaulting all setup/teardown to be strict or lazy. --- busted/block.lua | 61 ++++++++++++++-- busted/execute.lua | 5 +- busted/init.lua | 13 +++- busted/modules/filter_loader.lua | 4 ++ spec/cl_failing_support.lua | 66 +++++++++++++++++ spec/cl_spec.lua | 10 ++- spec/core_spec.lua | 119 +++++++++++++++++++++++++++++++ spec/export_spec.lua | 8 +++ 8 files changed, 276 insertions(+), 10 deletions(-) diff --git a/busted/block.lua b/busted/block.lua index cb496e26..396e19bc 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -48,6 +48,37 @@ return function(busted) return unpack(ret) end + function block.execAllOnce(descriptor, current, err) + local parent = busted.context.parent(current) + + if parent then + local success = block.execAllOnce(descriptor, parent) + if not success then + return success + end + end + + if not current[descriptor] then + current[descriptor] = {} + end + local list = current[descriptor] + if list.success ~= nil then + return list.success + end + + local success = true + for _, v in ipairs(list) do + if not exec(descriptor, v):success() then + if err then err(descriptor) end + success = false + end + end + + list.success = success + + return success + end + function block.execAll(descriptor, current, propagate, err) local parent = busted.context.parent(current) @@ -61,7 +92,7 @@ return function(busted) local list = current[descriptor] or {} local success = true - for _, v in pairs(list) do + for _, v in ipairs(list) do if not exec(descriptor, v):success() then if err then err(descriptor) end success = nil @@ -75,7 +106,7 @@ return function(busted) local list = current[descriptor] or {} local success = true - for _, v in pairs(list) do + for _, v in ipairs(list) do if not exec(descriptor, v):success() then if err then err(descriptor) end success = nil @@ -90,6 +121,25 @@ return function(busted) return success end + function block.lazySetup(element, err) + return block.execAllOnce('lazy_setup', element, err) + end + + function block.lazyTeardown(element, err) + if element.lazy_setup and element.lazy_setup.success ~= nil then + block.dexecAll('lazy_teardown', element, nil, err) + element.lazy_setup.success = nil + end + end + + function block.setup(element, err) + return block.execAll('strict_setup', element, nil, err) + end + + function block.teardown(element, err) + return block.dexecAll('strict_teardown', element, nil, err) + end + function block.execute(descriptor, element) if not element.env then element.env = {} end @@ -103,10 +153,13 @@ return function(busted) elseif busted.sort then sort(busted.context.children(element)) end - if block.execAll('setup', element) then + + if block.setup(element) then busted.execute(element) end - block.dexecAll('teardown', element) + + block.lazyTeardown(element) + block.teardown(element) end end diff --git a/busted/execute.lua b/busted/execute.lua index 17b9d4eb..2132d8ef 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -32,10 +32,11 @@ return function(busted) local root = busted.context.get() busted.publish({ 'suite', 'start' }, i, runs) - if block.execAll('setup', root) then + if block.setup(root) then busted.execute() end - block.dexecAll('teardown', root) + block.lazyTeardown(root) + block.teardown(root) busted.publish({ 'suite', 'end' }, i, runs) if busted.skipAll then diff --git a/busted/init.lua b/busted/init.lua index e624cfd2..3c73721b 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -19,6 +19,11 @@ local function init(busted) local parent = busted.context.parent(element) local finally + if not block.lazySetup(parent) then + -- skip test if any setup failed + return + end + if not element.env then element.env = {} end block.rejectAll(element) @@ -55,11 +60,15 @@ local function init(busted) busted.register('pending', pending) - busted.register('setup') - busted.register('teardown') + busted.register('lazy_setup') + busted.register('lazy_teardown') + busted.register('strict_setup') + busted.register('strict_teardown') busted.register('before_each') busted.register('after_each') + busted.alias('setup', 'strict_setup') + busted.alias('teardown', 'strict_teardown') busted.alias('context', 'describe') busted.alias('spec', 'it') busted.alias('test', 'it') diff --git a/busted/modules/filter_loader.lua b/busted/modules/filter_loader.lua index 1aaaba0b..161e0fe4 100644 --- a/busted/modules/filter_loader.lua +++ b/busted/modules/filter_loader.lua @@ -85,9 +85,13 @@ return function() busted.subscribe({ 'suite', 'start' }, ignoreAll, { priority = 1 }) busted.subscribe({ 'suite', 'end' }, ignoreAll, { priority = 1 }) applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'list', ignoreAll) + applyFilter({ 'lazy_setup', 'lazy_teardown' }, 'list', ignoreAll) + applyFilter({ 'strict_setup', 'strict_teardown' }, 'list', ignoreAll) applyFilter({ 'it', 'pending' }, 'list', printNameOnly) end + applyFilter({ 'lazy_setup', 'lazy_teardown' }, 'nokeepgoing', skipOnError) + applyFilter({ 'strict_setup', 'strict_teardown' }, 'nokeepgoing', skipOnError) applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'nokeepgoing', skipOnError) applyFilter({ 'file', 'describe', 'it', 'pending' }, 'nokeepgoing', skipOnError) diff --git a/spec/cl_failing_support.lua b/spec/cl_failing_support.lua index 86da16c2..21a85a5e 100644 --- a/spec/cl_failing_support.lua +++ b/spec/cl_failing_support.lua @@ -12,6 +12,11 @@ describe('bad support functions should fail, sync test', function() teardown(function() end) it('Tests nothing, should always fail due to failing support functions', function() + assert(false) + end) + + it('Tests nothing, should always fail due to failing support functions', function() + assert(false) end) end) @@ -48,6 +53,9 @@ describe('bad support functions should fail, sync test', function() it('Tests nothing, should always fail due to failing support functions', function() end) + + it('Tests nothing, should always fail due to failing support functions', function() + end) end) describe('bad teardown should properly fail a test', function() @@ -63,6 +71,27 @@ describe('bad support functions should fail, sync test', function() it('Tests nothing, should always fail due to failing support functions', function() end) + + it('Tests nothing, should always fail due to failing support functions', function() + end) + end) + + describe('bad setup/teardown should properly fail a test', function() + setup(function() + error('failing a setup method') + end) + + before_each(function() end) + + after_each(function() end) + + teardown(function() + error('failing a teardown method') + end) + + it('Tests nothing, should always fail due to failing support functions', function() + assert(false) + end) end) end) @@ -81,6 +110,9 @@ describe('bad support functions should fail, async test', function() it('Tests nothing, should always fail due to failing support functions', function() end) + + it('Tests nothing, should always fail due to failing support functions', function() + end) end) describe('bad before_each should properly fail a test, async', function() @@ -97,6 +129,9 @@ describe('bad support functions should fail, async test', function() it('Tests nothing, should always fail due to failing support functions', function() end) + + it('Tests nothing, should always fail due to failing support functions', function() + end) end) describe('bad after_each should properly fail a test, async', function() @@ -113,6 +148,9 @@ describe('bad support functions should fail, async test', function() it('Tests nothing, should always fail due to failing support functions', function() end) + + it('Tests nothing, should always fail due to failing support functions', function() + end) end) describe('bad teardown should properly fail a test, async', function() @@ -129,6 +167,34 @@ describe('bad support functions should fail, async test', function() it('Tests nothing, should always fail due to failing support functions', function() end) + + it('Tests nothing, should always fail due to failing support functions', function() + end) end) + + describe('bad setup/teardown should properly fail a test, async', function() + setup(function() + async() + error('failing a setup method') + end) + + before_each(function() end) + + after_each(function() end) + + teardown(function() + async() + error('failing a teardown method') + end) + + it('Tests nothing, should always fail due to failing support functions', function() + assert(false) + end) + + it('Tests nothing, should always fail due to failing support functions', function() + assert(false) + end) + end) + end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 9001d439..345e82d2 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -276,7 +276,7 @@ describe('Tests failing tests through the commandline', function() error_start() success, exitcode = execute(busted_cmd .. ' --pattern=cl_failing_support.lua$') assert.is_false(success) - assert.is_equal(9, exitcode) + assert.is_equal(16, exitcode) error_end() end) @@ -284,7 +284,7 @@ describe('Tests failing tests through the commandline', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_failing_support.lua$') local _, numErrors = result:gsub('Error %-> .-\n','') - assert.is_equal(9, numErrors) + assert.is_equal(16, numErrors) error_end() end) end) @@ -779,4 +779,10 @@ describe('Tests helper script', function() assert.is_false(success) assert.is_equal(3, exitcode) end) + + it('runs setup/teardown for mutiple runs', function() + local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') + assert.is_false(success) + assert.is_equal(4, exitcode) + end) end) diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 01f01691..db303d95 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -386,3 +386,122 @@ describe('tests unsupported functions in setup/before_each/after_each/teardown', it('tests nothing, all tests performed by support functions', function() end) end) + +describe('tests strict setup/teardown', function() + local setup_count = 0 + local teardown_count = 0 + + describe('in describe with no tests', function() + strict_setup(function() + setup_count = setup_count + 1 + end) + + strict_teardown(function() + teardown_count = teardown_count + 1 + end) + end) + + it('executes setup/teardown in previous block with no tests', function() + assert.is_equal(1, setup_count) + assert.is_equal(1, teardown_count) + end) +end) + +describe('tests lazy setup/teardown not run if no tests found in block', function() + lazy_setup(function() + assert(false, 'setup should not execute since no tests') + end) + + lazy_teardown(function() + assert(false, 'teardown should not execute since no tests') + end) +end) + +describe('tests lazy setup/teardown in describe with no tests', function() + local setup_count = 0 + local teardown_count = 0 + + describe('with nested describe with no tests', function() + lazy_setup(function() + setup_count = setup_count + 1 + end) + + lazy_teardown(function() + teardown_count = teardown_count + 1 + end) + + describe('with inner nested describe with no tests', function() + lazy_setup(function() + setup_count = setup_count + 1 + end) + + lazy_teardown(function() + teardown_count = teardown_count + 1 + end) + end) + end) + + it('does not run setup/teardown', function() + assert.is_equal(0, setup_count) + assert.is_equal(0, teardown_count) + end) +end) + +describe('tests lazy setup/teardown with nested tests', function() + local setup_count = 0 + local teardown_count = 0 + + lazy_setup(function() + setup_count = setup_count + 1 + end) + + lazy_teardown(function() + teardown_count = teardown_count + 1 + end) + + describe('nested describe with tests', function() + lazy_setup(function() + setup_count = setup_count + 1 + end) + + lazy_teardown(function() + teardown_count = teardown_count + 1 + end) + + it('runs all setups', function() + assert.is_equal(2, setup_count) + end) + + it('runs setups only once', function() + assert.is_equal(2, setup_count) + end) + + it('runs teardown after all tests complete', function() + assert.is_equal(0, teardown_count) + end) + end) + + describe('second nested describe', function() + lazy_teardown(function() + teardown_count = teardown_count + 1 + end) + + it('verify teardown ran after previous describe completes', function() + assert.is_equal(1, teardown_count) + end) + end) + + describe('another nested describe with tests', function() + lazy_setup(function() + setup_count = setup_count + 1 + end) + + it('runs setup for new describe', function() + assert.is_equal(3, setup_count) + end) + + it('verify teardown ran after previous describe completes', function() + assert.is_equal(2, teardown_count) + end) + end) +end) diff --git a/spec/export_spec.lua b/spec/export_spec.lua index efb83b3e..82a9ec52 100644 --- a/spec/export_spec.lua +++ b/spec/export_spec.lua @@ -10,6 +10,10 @@ describe('tests require "busted"', function() local teardown = teardown local before_each = before_each local after_each = after_each + local lazy_setup = lazy_setup + local lazy_teardown = lazy_teardown + local strict_setup = strict_setup + local strict_teardown = strict_teardown it('does not export init', function() assert.is_nil(require 'busted'.init) @@ -34,6 +38,10 @@ describe('tests require "busted"', function() it('exports support functions', function() assert.is_equal(setup, require 'busted'.setup) assert.is_equal(teardown, require 'busted'.teardown) + assert.is_equal(lazy_setup, require 'busted'.lazy_setup) + assert.is_equal(lazy_teardown, require 'busted'.lazy_teardown) + assert.is_equal(strict_setup, require 'busted'.strict_setup) + assert.is_equal(strict_teardown, require 'busted'.strict_teardown) assert.is_equal(before_each, require 'busted'.before_each) assert.is_equal(after_each, require 'busted'.after_each) end) From 053e52bac8099ea238ae77de394c4e47a2dfd4a6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 15 Mar 2015 01:01:53 -0700 Subject: [PATCH 181/293] Refactor context block aliasing This allows busted context block aliases to be created using the `register` function, where the `executor` is a previously registered descriptor. --- busted/core.lua | 22 ++++++++++++---------- busted/init.lua | 16 +++++++++------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 50ec3401..7c366ece 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -182,12 +182,19 @@ return function() end function busted.register(descriptor, executor) - executors[descriptor] = executor + local alias = nil + if type(executor) == 'string' then + alias = descriptor + descriptor = executor + executor = executors[descriptor] + else + executors[descriptor] = executor + end local publisher = function(name, fn) if not fn and type(name) == 'function' then fn = name - name = nil + name = alias end local trace @@ -204,9 +211,10 @@ return function() if fn then publish(fn) else return publish end end - busted.executors[descriptor] = publisher + local edescriptor = alias or descriptor + busted.executors[edescriptor] = publisher if descriptor ~= 'file' then - busted.export(descriptor, publisher) + busted.export(edescriptor, publisher) end busted.subscribe({ 'register', descriptor }, function(name, fn, trace) @@ -228,12 +236,6 @@ return function() end) end - function busted.alias(alias, descriptor) - local publisher = busted.executors[descriptor] - busted.executors[alias] = publisher - busted.export(alias, publisher) - end - function busted.execute(current) if not current then current = busted.context.get() end for _, v in pairs(busted.context.children(current)) do diff --git a/busted/init.lua b/busted/init.lua index 3c73721b..560af3b8 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -60,18 +60,20 @@ local function init(busted) busted.register('pending', pending) + busted.register('before_each') + busted.register('after_each') + busted.register('lazy_setup') busted.register('lazy_teardown') busted.register('strict_setup') busted.register('strict_teardown') - busted.register('before_each') - busted.register('after_each') - busted.alias('setup', 'strict_setup') - busted.alias('teardown', 'strict_teardown') - busted.alias('context', 'describe') - busted.alias('spec', 'it') - busted.alias('test', 'it') + busted.register('setup', 'strict_setup') + busted.register('teardown', 'strict_teardown') + + busted.register('context', 'describe') + busted.register('spec', 'it') + busted.register('test', 'it') local assert = require 'luassert' local spy = require 'luassert.spy' From e8d23e8ec21a5efa5ded5c6d47aaf4dcec7d1ba6 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 15 Mar 2015 01:10:34 -0700 Subject: [PATCH 182/293] Default lazy setup/teardown with command-line flag This adds a command-line flag to default setup/teardown support functions to be lazy. --- busted/modules/cli.lua | 1 + busted/runner.lua | 6 ++++++ completions/bash/busted.bash | 1 + completions/zsh/_busted | 1 + spec/cl_spec.lua | 24 ++++++++++++++++++++++++ 5 files changed, 33 insertions(+) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index c28f0924..f7a85692 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -126,6 +126,7 @@ return function(options) cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) cli:add_flag('-l, --list', 'list the names of all tests instead of running them', processOption) + cli:add_flag('--lazy', 'use lazy setup/teardown as the default', processOption) cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) diff --git a/busted/runner.lua b/busted/runner.lua index b1e77345..a38b724a 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -50,6 +50,12 @@ return function(options) luacov() end + -- If lazy is enabled, make lazy setup/teardown the default + if cliArgs.lazy then + busted.register('setup', 'lazy_setup') + busted.register('teardown', 'lazy_teardown') + end + -- Add additional package paths based on lpath and cpath cliArgs if #cliArgs.lpath > 0 then package.path = (cliArgs.lpath .. ';' .. package.path):gsub(';;',';') diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 3db7d639..c4833502 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -154,6 +154,7 @@ _busted() { -s --enable-sound -Xoutput -Xhelper + --lazy --no-keep-going --no-recursive --shuffle --shuffle-tests --shuffle-files diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 449d46ae..22ff3809 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -19,6 +19,7 @@ _busted_args=( "--suppress-pending[Suppress 'pending' test output]" "--version[Prints the program version and exits]" "(-l --list)"{-l,--list}"[List the names of all tests instead of running them]" +"--lazy[Use lazy setup/teardown as the default]" "--no-keep-going[Quit after first error or failure]" "--no-recursive[Do not recurse into subdirectories]" "--helper[A helper script that is run before tests]:files:_files" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 345e82d2..f4c7c930 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -171,6 +171,24 @@ describe('Tests the busted command-line options', function() error_end() end) + it('tests running with --lazy specified', function() + local success, exitcode + error_start() + success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$') + assert.is_false(success) + assert.is_equal(7, exitcode) + success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$ --tags=tag1') + assert.is_false(success) + assert.is_equal(2, exitcode) + success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$ --tags=tag1,tag2') + assert.is_false(success) + assert.is_equal(3, exitcode) + success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$ --tags=tag1 --tags=tag2') + assert.is_false(success) + assert.is_equal(3, exitcode) + error_end() + end) + it('tests running with -l specified', function() local result = run(busted_cmd .. ' -l --pattern=cl_list.lua$') local expected = './spec/cl_list.lua:4: Tests list test 1\n' .. @@ -785,4 +803,10 @@ describe('Tests helper script', function() assert.is_false(success) assert.is_equal(4, exitcode) end) + + it('runs setup/teardown for mutiple runs with --lazy', function() + local success, exitcode = execute(busted_cmd .. ' --lazy --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') + assert.is_false(success) + assert.is_equal(4, exitcode) + end) end) From 551ecb190f5f291d2d20923acc4e7ab267d747e5 Mon Sep 17 00:00:00 2001 From: mpeterv Date: Tue, 17 Mar 2015 15:36:13 +0300 Subject: [PATCH 183/293] Add Spanish language to rockspec --- busted-scm-0.rockspec | 1 + 1 file changed, 1 insertion(+) diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 051ab92b..81fec3af 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -66,6 +66,7 @@ build = { ['busted.languages.en'] = 'busted/languages/en.lua', ['busted.languages.ar'] = 'busted/languages/ar.lua', ['busted.languages.de'] = 'busted/languages/de.lua', + ['busted.languages.es'] = 'busted/languages/es.lua', ['busted.languages.fr'] = 'busted/languages/fr.lua', ['busted.languages.ja'] = 'busted/languages/ja.lua', ['busted.languages.nl'] = 'busted/languages/nl.lua', From 1c80cd9fd70a3188eac147d8c5df3bba47015dd3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 17 Mar 2015 12:09:17 -0700 Subject: [PATCH 184/293] Add Spanish language to rockspec --- busted-2.0.rc7-0.rockspec | 1 + 1 file changed, 1 insertion(+) diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index 09379f98..abd702c8 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -67,6 +67,7 @@ build = { ['busted.languages.en'] = 'busted/languages/en.lua', ['busted.languages.ar'] = 'busted/languages/ar.lua', ['busted.languages.de'] = 'busted/languages/de.lua', + ['busted.languages.es'] = 'busted/languages/es.lua', ['busted.languages.fr'] = 'busted/languages/fr.lua', ['busted.languages.ja'] = 'busted/languages/ja.lua', ['busted.languages.nl'] = 'busted/languages/nl.lua', From 219628ce4a64eaf39f0791b30cdd7e2227271aeb Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 18 Mar 2015 14:00:34 -0700 Subject: [PATCH 185/293] Add more tests for lazy/strict setup/teardown --- spec/core_spec.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/core_spec.lua b/spec/core_spec.lua index db303d95..cd1c4ea6 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -346,6 +346,13 @@ describe('tests unsupported functions', function() assert.has_error(teardown, "'teardown' not supported inside current context block") end) + it('it block throws error on lazy/strict setup/teardown', function() + assert.has_error(lazy_setup, "'lazy_setup' not supported inside current context block") + assert.has_error(lazy_teardown, "'lazy_teardown' not supported inside current context block") + assert.has_error(strict_setup, "'strict_setup' not supported inside current context block") + assert.has_error(strict_teardown, "'strict_teardown' not supported inside current context block") + end) + it('it block throws error on randomize', function() assert.has_error(randomize, "'randomize' not supported inside current context block") end) @@ -376,6 +383,11 @@ describe('tests unsupported functions in setup/before_each/after_each/teardown', assert.has_error(before_each, "'before_each' not supported inside current context block") assert.has_error(after_each, "'after_each' not supported inside current context block") assert.has_error(teardown, "'teardown' not supported inside current context block") + + assert.has_error(lazy_setup, "'lazy_setup' not supported inside current context block") + assert.has_error(lazy_teardown, "'lazy_teardown' not supported inside current context block") + assert.has_error(strict_setup, "'strict_setup' not supported inside current context block") + assert.has_error(strict_teardown, "'strict_teardown' not supported inside current context block") end setup(testUnsupported) From 47e0bfedd9fd4d55d255c6d67291cbbf174d21e0 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 17 Mar 2015 16:58:06 -0700 Subject: [PATCH 186/293] Support for insulate/expose contexts This adds `describe` aliases that allow one to insulate the test environment or expose the test environment to outer context blocks. Test environment insulation saves the global table `_G` and the currently loaded packages `package.loaded`, restoring them to their original state at the completion of an `insulate` block. Exposing a test environment exports any changes made to `_G` and `package.loaded` to subsequent context blocks. In addition, any global variables created inside an `expose` block are created in the environment of the context block 2 levels out. Using `expose` at the root of a file will promote any requires and globals to the root environment, which will then spillover into subsequent tests. The `insulate` and `expose` blocks can be nested inside other blocks, as well as nested inside of each other. This provides full control of the level of isolation that may be desired. By default all file contexts are insulated. --- busted/block.lua | 10 --- busted/context.lua | 53 ++++++++++-- busted/core.lua | 22 ++++- busted/init.lua | 16 ++-- spec/core_spec.lua | 18 ++++ spec/export_spec.lua | 4 + spec/expose_file1.lua | 9 ++ spec/expose_file2.lua | 13 +++ spec/file_sandbox1_spec.lua | 14 ---- spec/file_sandbox2_spec.lua | 14 ---- spec/insulate-expose_spec.lua | 151 ++++++++++++++++++++++++++++++++++ spec/insulate_file1.lua | 14 ++++ spec/insulate_file2.lua | 15 ++++ 13 files changed, 297 insertions(+), 56 deletions(-) create mode 100644 spec/expose_file1.lua create mode 100644 spec/expose_file2.lua delete mode 100644 spec/file_sandbox1_spec.lua delete mode 100644 spec/file_sandbox2_spec.lua create mode 100644 spec/insulate-expose_spec.lua create mode 100644 spec/insulate_file1.lua create mode 100644 spec/insulate_file2.lua diff --git a/busted/block.lua b/busted/block.lua index 396e19bc..fc2609b1 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -33,17 +33,7 @@ return function(busted) local function exec(descriptor, element) if not element.env then element.env = {} end - block.rejectAll(element) - - local parent = busted.context.parent(element) - setmetatable(element.env, { - __newindex = function(self, key, value) - if not parent.env then parent.env = {} end - parent.env[key] = value - end - }) - local ret = { busted.safe(descriptor, element.run, element) } return unpack(ret) end diff --git a/busted/context.lua b/busted/context.lua index 4cf0f3b5..c2e28921 100644 --- a/busted/context.lua +++ b/busted/context.lua @@ -29,11 +29,54 @@ return function() local parents = {} local children = {} local stack = {} + local states = {} function context.ref() local ref = {} local ctx = data + local function unwrap(element, levels) + local levels = levels or 1 + local parent = element + for i = 1, levels do + parent = ref.parent(parent) + if not parent then break end + end + if not element.env then element.env = {} end + setmetatable(element.env, { + __newindex = function(self, key, value) + if not parent then + _G[key] = value + else + if not parent.env then parent.env = {} end + parent.env[key] = value + end + end + }) + end + + local function push_state(current) + local state = false + if current.attributes.envmode == 'insulate' then + state = save() + elseif current.attributes.envmode == 'unwrap' then + unwrap(current) + elseif current.attributes.envmode == 'expose' then + unwrap(current, 2) + end + table.insert(states, state) + end + + local function pop_state(current) + local state = table.remove(states) + if current.attributes.envmode == 'expose' then + states[#states] = states[#states] and save() + end + if state then + restore(state) + end + end + function ref.get(key) if not key then return ctx end return ctx[key] @@ -48,6 +91,7 @@ return function() parents = {} children = {} stack = {} + states = {} ctx = data end @@ -67,9 +111,7 @@ return function() function ref.push(current) if not parents[current] then error('Detached child. Cannot push.') end - if ctx ~= current and current.descriptor == 'file' then - current.state = save() - end + if ctx ~= current then push_state(current) end table.insert(stack, ctx) ctx = current end @@ -77,10 +119,7 @@ return function() function ref.pop() local current = ctx ctx = table.remove(stack) - if ctx ~= current and current.state then - restore(current.state) - current.state = nil - end + if ctx ~= current then pop_state(current) end if not ctx then error('Context stack empty. Cannot pop.') end end diff --git a/busted/core.lua b/busted/core.lua index 7c366ece..a0b049d5 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -31,6 +31,10 @@ local function hasToString(obj) return type(obj) == 'string' or (getmetatable(obj) or {}).__tostring end +local function isCallable(obj) + return (type(obj) == 'function' or (getmetatable(obj) or {}).__call) +end + return function() local mediator = require 'mediator'() @@ -45,6 +49,7 @@ return function() busted.modules = {} busted.executors = {} local executors = {} + local eattributes = {} busted.status = require 'busted.status' @@ -145,7 +150,7 @@ return function() end function busted.wrap(callable) - if (type(callable) == 'function' or getmetatable(callable).__call) then + if isCallable(callable) then -- prioritize __call if it exists, like in files environment.wrap((getmetatable(callable) or {}).__call or callable) end @@ -181,14 +186,22 @@ return function() environment.set(key, value) end - function busted.register(descriptor, executor) + function busted.register(descriptor, executor, attributes) local alias = nil if type(executor) == 'string' then alias = descriptor descriptor = executor executor = executors[descriptor] + attributes = attributes or eattributes[descriptor] + executors[alias] = executor + eattributes[alias] = attributes else + if executor ~= nil and not isCallable(executor) then + attributes = executor + executor = nil + end executors[descriptor] = executor + eattributes[descriptor] = attributes end local publisher = function(name, fn) @@ -205,7 +218,7 @@ return function() end local publish = function(f) - busted.publish({ 'register', descriptor }, name, f, trace) + busted.publish({ 'register', descriptor }, name, f, trace, attributes) end if fn then publish(fn) else return publish end @@ -217,10 +230,11 @@ return function() busted.export(edescriptor, publisher) end - busted.subscribe({ 'register', descriptor }, function(name, fn, trace) + busted.subscribe({ 'register', descriptor }, function(name, fn, trace, attributes) local ctx = busted.context.get() local plugin = { descriptor = descriptor, + attributes = attributes or {}, name = name, run = fn, trace = trace diff --git a/busted/init.lua b/busted/init.lua index 560af3b8..151e62b3 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -52,21 +52,23 @@ local function init(busted) busted.publish({ 'test', 'end' }, element, parent, 'pending') end - busted.register('file', file) + busted.register('file', file, { envmode = 'insulate' }) busted.register('describe', describe) + busted.register('insulate', 'describe', { envmode = 'insulate' }) + busted.register('expose', 'describe', { envmode = 'expose' }) busted.register('it', it) busted.register('pending', pending) - busted.register('before_each') - busted.register('after_each') + busted.register('before_each', { envmode = 'unwrap' }) + busted.register('after_each', { envmode = 'unwrap' }) - busted.register('lazy_setup') - busted.register('lazy_teardown') - busted.register('strict_setup') - busted.register('strict_teardown') + busted.register('lazy_setup', { envmode = 'unwrap' }) + busted.register('lazy_teardown', { envmode = 'unwrap' }) + busted.register('strict_setup', { envmode = 'unwrap' }) + busted.register('strict_teardown', { envmode = 'unwrap' }) busted.register('setup', 'strict_setup') busted.register('teardown', 'strict_teardown') diff --git a/spec/core_spec.lua b/spec/core_spec.lua index cd1c4ea6..9d61bbbf 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -283,6 +283,16 @@ describe('tests environment', function() end) end) +describe('tests clean environment', function() + it('globals in previous describe are not available', function() + assert.is_nil(global) + assert.is_nil(globalsetup) + assert.is_nil(globalbefore) + assert.is_nil(globalafter) + assert.is_nil(globalteardown) + end) +end) + describe 'tests syntactic sugar' (function() it 'works' (function() assert(true) @@ -333,6 +343,11 @@ describe('tests unsupported functions', function() assert.has_error(context, "'context' not supported inside current context block") end) + it('it block throws error on insulate/expose', function() + assert.has_error(insulate, "'insulate' not supported inside current context block") + assert.has_error(expose, "'expose' not supported inside current context block") + end) + it('it block throws error on it/spec/test', function() assert.has_error(it, "'it' not supported inside current context block") assert.has_error(spec, "'spec' not supported inside current context block") @@ -373,6 +388,9 @@ describe('tests unsupported functions in setup/before_each/after_each/teardown', assert.has_error(describe, "'describe' not supported inside current context block") assert.has_error(context, "'context' not supported inside current context block") + assert.has_error(insulate, "'insulate' not supported inside current context block") + assert.has_error(expose, "'expose' not supported inside current context block") + assert.has_error(pending, "'pending' not supported inside current context block") assert.has_error(it, "'it' not supported inside current context block") diff --git a/spec/export_spec.lua b/spec/export_spec.lua index 82a9ec52..5b918ca6 100644 --- a/spec/export_spec.lua +++ b/spec/export_spec.lua @@ -2,6 +2,8 @@ describe('tests require "busted"', function() local describe = describe local context = context + local insulate = insulate + local expose = expose local it = it local pending = pending local spec = spec @@ -31,6 +33,8 @@ describe('tests require "busted"', function() it('exports aliases', function() assert.is_equal(context, require 'busted'.context) + assert.is_equal(insulate, require 'busted'.insulate) + assert.is_equal(expose, require 'busted'.expose) assert.is_equal(spec, require 'busted'.spec) assert.is_equal(test, require 'busted'.test) end) diff --git a/spec/expose_file1.lua b/spec/expose_file1.lua new file mode 100644 index 00000000..4df74ee9 --- /dev/null +++ b/spec/expose_file1.lua @@ -0,0 +1,9 @@ +expose('Tests expose from file root', function() + pl = require 'pl' + _G.global_var = 'this global is in _G' + + it('loads global environment with "List"', function() + assert.is_not_nil(pl) + assert.is_not_nil(List) + end) +end) diff --git a/spec/expose_file2.lua b/spec/expose_file2.lua new file mode 100644 index 00000000..63fd5496 --- /dev/null +++ b/spec/expose_file2.lua @@ -0,0 +1,13 @@ +describe('Tests environment exposed from previous file', function() + it('global environment still has "List"', function() + assert.is_nil(_G.pl) + assert.is_not_nil(pl) + assert.is_equal('this global is in _G', _G.global_var) + assert.is_not_nil(List) + end) + + it('global environment still has "pl" packages loaded', function() + assert.is_not_nil(package.loaded['pl']) + assert.is_not_nil(package.loaded['pl.List']) + end) +end) diff --git a/spec/file_sandbox1_spec.lua b/spec/file_sandbox1_spec.lua deleted file mode 100644 index a6d695fe..00000000 --- a/spec/file_sandbox1_spec.lua +++ /dev/null @@ -1,14 +0,0 @@ -require 'pl' - -describe('require "pl" in this file', function() - it('loads global environment with "List"', function() - assert.is_not_nil(List) - end) -end) - -describe('require "socket" in another file', function() - it('does not keep "socket" in environment', function() - assert.is_nil(socket) - assert.is_nil(package.loaded.socket) - end) -end) diff --git a/spec/file_sandbox2_spec.lua b/spec/file_sandbox2_spec.lua deleted file mode 100644 index 83d99895..00000000 --- a/spec/file_sandbox2_spec.lua +++ /dev/null @@ -1,14 +0,0 @@ -socket = require 'socket' - -describe('require "socket" in this file', function() - it('loads environment with "socket"', function() - assert.is_not_nil(socket) - end) -end) - -describe('require "pl" in another file', function() - it('does not keep "List" in environment', function() - assert.is_nil(List) - assert.is_nil(package.loaded['pl.List']) - end) -end) diff --git a/spec/insulate-expose_spec.lua b/spec/insulate-expose_spec.lua new file mode 100644 index 00000000..acccc38d --- /dev/null +++ b/spec/insulate-expose_spec.lua @@ -0,0 +1,151 @@ +assert.is_nil(package.loaded.pl) +assert.is_nil(package.loaded['pl.file']) + +describe('Tests insulation', function() + insulate('environment inside insulate', function() + pl = require 'pl' + _G.insuated_global = true + + it('updates insuated global table _G', function() + assert.is_not_nil(insuated_global) + assert.is_not_nil(_G.insuated_global) + end) + + it('updates package.loaded', function() + assert.is_not_nil(pl) + assert.is_not_nil(List) + assert.is_not_nil(package.loaded.pl) + assert.is_not_nil(package.loaded['pl.List']) + end) + end) + + describe('environment after insulate', function() + it('restores insuated global table _G', function() + assert.is_nil(insuated_global) + assert.is_nil(_G.insuated_global) + end) + + it('restores package.loaded', function() + assert.is_nil(pl) + assert.is_nil(List) + assert.is_nil(package.loaded.pl) + assert.is_nil(package.loaded['pl.List']) + end) + end) +end) + +insulate('', function() + describe('Tests expose', function() + insulate('inside insulate block', function() + expose('tests environment inside expose block', function() + pl = require 'pl' + exposed_global = true + _G.global = true + + it('creates exposed global', function() + assert.is_not_nil(exposed_global) + assert.is_nil(_G.exposed_global) + end) + + it('updates global table _G', function() + assert.is_not_nil(global) + assert.is_not_nil(_G.global) + end) + + it('updates package.loaded', function() + assert.is_not_nil(pl) + assert.is_not_nil(List) + assert.is_not_nil(package.loaded.pl) + assert.is_not_nil(package.loaded['pl.List']) + end) + end) + end) + + describe('neutralizes insulation', function() + it('creates exposed global in outer block', function() + assert.is_not_nil(exposed_global) + assert.is_nil(_G.exposed_global) + end) + + it('does not restore global table _G', function() + assert.is_not_nil(global) + assert.is_not_nil(_G.global) + end) + + it('does not restore package.loaded', function() + assert.is_not_nil(pl) + assert.is_not_nil(List) + assert.is_not_nil(package.loaded.pl) + assert.is_not_nil(package.loaded['pl.List']) + end) + end) + end) + + it('Tests exposed globals does not exist in outer most block', function() + assert.is_nil(pl) + assert.is_nil(exposed_global) + assert.is_nil(_G.exposed_global) + end) + + it('Tests global table _G persists without insulate', function() + assert.is_not_nil(global) + assert.is_not_nil(_G.global) + end) + + it('Tests package.loaded persists without insulate', function() + assert.is_not_nil(List) + assert.is_not_nil(package.loaded.pl) + assert.is_not_nil(package.loaded['pl.List']) + end) +end) + +describe('Tests after insulating an expose block', function() + it('restores global table _G', function() + assert.is_nil(global) + assert.is_nil(_G.global) + end) + + it('restores package.loaded', function() + assert.is_nil(pl) + assert.is_nil(List) + assert.is_nil(package.loaded.pl) + assert.is_nil(package.loaded['pl.List']) + end) +end) + +describe('Tests insulate/expose', function() + local path = require 'pl.path' + local utils = require 'pl.utils' + local busted_cmd = path.is_windows and 'lua bin/busted' or 'bin/busted' + local ditch = path.is_windows and ' 1> NUL 2>NUL' or ' > /dev/null 2>&1' + + local execute = function(cmd) + local success, exitcode = utils.execute(cmd..ditch) + if exitcode > 255 then + exitcode = math.floor(exitcode/256), exitcode - math.floor(exitcode/256)*256 + end + return not not success, exitcode + end + + describe('file insulation', function() + it('works between files', function() + local success, exitcode = execute(busted_cmd .. ' spec/insulate_file1.lua spec/insulate_file2.lua') + assert.is_true(success) + assert.is_equal(0, exitcode) + end) + + it('works between files independent of order', function() + local success, exitcode = execute(busted_cmd .. ' spec/insulate_file2.lua spec/insulate_file1.lua') + assert.is_true(success) + assert.is_equal(0, exitcode) + end) + end) + + describe('expose from file context', function() + it('works between files', function() + local success, exitcode = execute(busted_cmd .. ' spec/expose_file1.lua spec/expose_file2.lua') + assert.is_true(success) + assert.is_equal(0, exitcode) + end) + end) +end) diff --git a/spec/insulate_file1.lua b/spec/insulate_file1.lua new file mode 100644 index 00000000..1a7d6014 --- /dev/null +++ b/spec/insulate_file1.lua @@ -0,0 +1,14 @@ +require 'pl' + +describe('Tests require "pl" in this file', function() + it('loads global environment with "List"', function() + assert.is_not_nil(List) + end) +end) + +describe('Tests require "cl_test_module" in another file', function() + it('does not keep test_module in environment', function() + assert.is_nil(test_module) + assert.is_nil(package.loaded['spec.cl_test_module']) + end) +end) diff --git a/spec/insulate_file2.lua b/spec/insulate_file2.lua new file mode 100644 index 00000000..d2b168d7 --- /dev/null +++ b/spec/insulate_file2.lua @@ -0,0 +1,15 @@ +test_module = require 'spec.cl_test_module' + +describe('Tests require "cl_test_module" in this file', function() + it('loads environment with "cl_test_module"', function() + assert.is_not_nil(test_module) + assert.is_not_nil(package.loaded['spec.cl_test_module']) + end) +end) + +describe('Tests require "pl" in another file', function() + it('does not keep "List" in environment', function() + assert.is_nil(List) + assert.is_nil(package.loaded['pl.List']) + end) +end) From ce5afb86058ad30e7786bab212eb363c8a911df9 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 18 Mar 2015 14:51:02 -0700 Subject: [PATCH 187/293] Add --no-auto-insulate command-line flag This flag disables automatic test insulation at the file level. When this flag is enabled, all test insulation must be explicit, using the `insulate` block. The file context will still wrap itself in a `setfenv` sandbox, but the global tables `_G` and `package.loaded` will not be saved/restored. --- busted/modules/cli.lua | 1 + busted/runner.lua | 5 +++++ completions/bash/busted.bash | 1 + completions/zsh/_busted | 1 + spec/cl_spec.lua | 11 +++++++++++ 5 files changed, 19 insertions(+) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 0ce275e5..b2ca0454 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -127,6 +127,7 @@ return function(options) cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) cli:add_flag('-l, --list', 'list the names of all tests instead of running them', processOption) cli:add_flag('--lazy', 'use lazy setup/teardown as the default', processOption) + cli:add_flag('--no-auto-insulate', 'disable file insulation', processOption) cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) diff --git a/busted/runner.lua b/busted/runner.lua index 14308ca7..e2327be9 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -55,6 +55,11 @@ return function(options) luacov() end + -- If auto-insulate is disabled, re-register file without insulation + if cliArgs['no-auto-insulate'] then + busted.register('file', 'file', {}) + end + -- If lazy is enabled, make lazy setup/teardown the default if cliArgs.lazy then busted.register('setup', 'lazy_setup') diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 622d8511..b21838d2 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -155,6 +155,7 @@ _busted() { -Xoutput -Xhelper --lazy + --no-auto-insulate --no-keep-going --no-recursive --shuffle --shuffle-tests --shuffle-files diff --git a/completions/zsh/_busted b/completions/zsh/_busted index bac08171..b557309d 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -20,6 +20,7 @@ _busted_args=( "--version[Prints the program version and exits]" "(-l --list)"{-l,--list}"[List the names of all tests instead of running them]" "--lazy[Use lazy setup/teardown as the default]" +"--no-auto-insulate[Disable file insulation]" "--no-keep-going[Quit after first error or failure]" "--no-recursive[Do not recurse into subdirectories]" "--helper[A helper script that is run before tests]:files:_files" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 7e899305..e127b5b5 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -734,6 +734,17 @@ describe('Tests no-recursive commandline option', function() end) end) +describe('Tests no-auto-insulate commandline option', function() + it('does not insulate test files', function() + local success, exitcode + error_start() + success, exitcode = execute(busted_cmd .. ' --no-auto-insulate --pattern=insulate_file.*.lua$') + assert.is_false(success) + assert.is_equal(1, exitcode) + error_end() + end) +end) + describe('Tests Xoutput commandline option', function() it('forwards no options to output handler when no options specified', function() local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua --pattern=cl_success.lua$') From 8a4d223c5ae4ace8d88d4ee3ca79020f6e67ae21 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 18 Mar 2015 22:36:21 -0700 Subject: [PATCH 188/293] Update TAP output handler This updates the TAP output handler to output the result of each test as it completes, instead of all test results at the end of a suite. When the verbose option is enabled, print the test name at test start. Also update TAP output to report skipped tests and errors occurring outside of tests. --- busted/outputHandlers/TAP.lua | 92 +++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index 08ead59f..7d5ebab3 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -3,50 +3,82 @@ local pretty = require 'pl.pretty' return function(options, busted) local handler = require 'busted.outputHandlers.base'(busted) + local success = 'ok %u - %s' + local failure = 'not ' .. success + local skip = 'ok %u - # SKIP %s' + local counter = 0 + + handler.suiteReset = function() + counter = 0 + return nil, true + end + handler.suiteEnd = function() - local total = handler.successesCount + handler.errorsCount + handler.failuresCount - print('1..' .. total) + print('1..' .. counter) + return nil, true + end - local success = 'ok %u - %s' - local failure = 'not ' .. success - local counter = 0 + local function showFailure(t) + local message = t.message + local trace = t.trace or {} - for i,t in pairs(handler.successes) do - counter = counter + 1 - print(success:format(counter, t.name)) + if message == nil then + message = 'Nil error' + elseif type(message) ~= 'string' then + message = pretty.write(message) end - local showFailure = function(t) - counter = counter + 1 - local message = t.message - local trace = t.trace or {} - - if message == nil then - message = 'Nil error' - elseif type(message) ~= 'string' then - message = pretty.write(message) - end - - print(failure:format(counter, t.name)) - print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) - if t.randomseed then print('# Random seed: ' .. t.randomseed) end - print('# Failure message: ' .. message:gsub('\n', '\n# ')) - if options.verbose and trace.traceback then - print('# ' .. trace.traceback:gsub('^\n', '', 1):gsub('\n', '\n# ')) - end + print(failure:format(counter, t.name)) + print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) + if t.randomseed then print('# Random seed: ' .. t.randomseed) end + print('# Failure message: ' .. message:gsub('\n', '\n# ')) + if options.verbose and trace.traceback then + print('# ' .. trace.traceback:gsub('^\n', '', 1):gsub('\n', '\n# ')) end + end - for i,t in pairs(handler.errors) do - showFailure(t) + handler.testStart = function(element, parent) + local trace = element.trace + if options.verbose and trace and trace.short_src then + local fileline = trace.short_src .. ' @ ' .. trace.currentline .. ': ' + local testName = fileline .. handler.getFullName(element) + print('# ' .. testName) end - for i,t in pairs(handler.failures) do - showFailure(t) + + return nil, true + end + + handler.testEnd = function(element, parent, status, trace) + counter = counter + 1 + if status == 'success' then + local t = handler.successes[#handler.successes] + print(success:format(counter, t.name)) + elseif status == 'pending' then + local t = handler.pendings[#handler.pendings] + print(skip:format(counter, (t.message or t.name))) + elseif status == 'failure' then + showFailure(handler.failures[#handler.failures]) + elseif status == 'error' then + showFailure(handler.errors[#handler.errors]) + end + + return nil, true + end + + handler.error = function(element, parent, message, debug) + if element.descriptor ~= 'it' then + counter = counter + 1 + showFailure(handler.errors[#handler.errors]) end return nil, true end + busted.subscribe({ 'suite', 'reset' }, handler.suiteReset) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) + busted.subscribe({ 'test', 'start' }, handler.testStart) + busted.subscribe({ 'test', 'end' }, handler.testEnd) + busted.subscribe({ 'error' }, handler.error) return handler end From 607db71bc01435da4c547c39b22226c8e0391b08 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Mar 2015 22:08:07 -0700 Subject: [PATCH 189/293] Fix --no-keep-going to skip support functions If the --no-keep-going flag is set, then skip support functions after an error is encountered. --- busted/modules/filter_loader.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/modules/filter_loader.lua b/busted/modules/filter_loader.lua index 161e0fe4..98a0fa5d 100644 --- a/busted/modules/filter_loader.lua +++ b/busted/modules/filter_loader.lua @@ -70,7 +70,7 @@ return function() end local skipOnError = function() - return nil, not busted.skippAll + return nil, not busted.skipAll end local applyFilter = function(descriptors, name, fn) From 524e698089bafa26dce319b877e7224e7c37abf5 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Mar 2015 21:43:29 -0700 Subject: [PATCH 190/293] Refactor overriding assert error with fail Refactor the way `error` is replaced with `busted.fail` in the `assert` functions to use a more generic function environment binding. --- busted/core.lua | 4 ++-- busted/init.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index a0b049d5..690aaf63 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -141,11 +141,11 @@ return function() throw(p) end - function busted.replaceErrorWithFail(callable) + function busted.bindfenv(callable, var, value) local env = {} local f = (getmetatable(callable) or {}).__call or callable setmetatable(env, { __index = getfenv(f) }) - env.error = busted.fail + env[var] = value setfenv(f, env) end diff --git a/busted/init.lua b/busted/init.lua index 151e62b3..8d76f0e9 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -91,8 +91,8 @@ local function init(busted) busted.exportApi('subscribe', busted.subscribe) busted.exportApi('unsubscribe', busted.unsubscribe) - busted.replaceErrorWithFail(assert) - busted.replaceErrorWithFail(assert.is_true) + busted.bindfenv(assert, 'error', busted.fail) + busted.bindfenv(assert.is_true, 'error', busted.fail) return busted end From 06d5fb0778c600b9c602839d1567c24aab0c1fe1 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Mar 2015 21:48:59 -0700 Subject: [PATCH 191/293] Export functions to busted API This exports the following functions/variables so they can be accessible to helper modules: - busted.bindfenv - busted.parent - busted.fail - busted.version --- busted/core.lua | 4 ++-- busted/init.lua | 7 ++++++- spec/export_spec.lua | 7 +++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 690aaf63..c36ba652 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -46,7 +46,7 @@ return function() local environment = require 'busted.environment'(busted.context) - busted.modules = {} + busted.api = {} busted.executors = {} local executors = {} local eattributes = {} @@ -178,7 +178,7 @@ return function() end function busted.exportApi(key, value) - busted.modules[key] = value + busted.api[key] = value end function busted.export(key, value) diff --git a/busted/init.lua b/busted/init.lua index 8d76f0e9..285b4dd2 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -91,6 +91,11 @@ local function init(busted) busted.exportApi('subscribe', busted.subscribe) busted.exportApi('unsubscribe', busted.unsubscribe) + busted.exportApi('bindfenv', busted.bindfenv) + busted.exportApi('fail', busted.fail) + busted.exportApi('parent', busted.context.parent) + busted.exportApi('version', busted.version) + busted.bindfenv(assert, 'error', busted.fail) busted.bindfenv(assert.is_true, 'error', busted.fail) @@ -103,7 +108,7 @@ return setmetatable({}, { return setmetatable(self, { __index = function(self, key) - return busted.modules[key] + return busted.api[key] end, __newindex = function(self, key, value) diff --git a/spec/export_spec.lua b/spec/export_spec.lua index 5b918ca6..b0ce3ab1 100644 --- a/spec/export_spec.lua +++ b/spec/export_spec.lua @@ -70,6 +70,13 @@ describe('tests require "busted"', function() assert.is_equal(sub, unsub) end) + it('exports other functions/variables', function() + assert.is_function(require 'busted'.bindfenv) + assert.is_function(require 'busted'.fail) + assert.is_function(require 'busted'.parent) + assert.is_string(require 'busted'.version) + end) + it('functions cannot be overwritten', function() local foo = function() assert(false) end assert.has_error(function() require 'busted'.it = foo end) From ae4dac637834d0f383f6e32d0423c214b7b0eb82 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Mar 2015 21:35:57 -0700 Subject: [PATCH 192/293] Improve configuration task loading This adds a special global option `_all` that is inherited by all other configuration options unless explicitly overwritten. --- busted/modules/configuration_loader.lua | 4 ++++ spec/.hidden/.busted | 4 ++++ spec/modules/cli_spec.lua | 3 ++- spec/modules/configuration_loader_spec.lua | 11 +++++++++-- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index 95593e3b..fbefd9a1 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -22,6 +22,10 @@ return function() config = tablex.merge(configFile.default, config, true) end + if type(configFile._all) == 'table' then + config = tablex.merge(configFile._all, config, true) + end + config = tablex.merge(defaults, config, true) return config diff --git a/spec/.hidden/.busted b/spec/.hidden/.busted index d4555559..7ec40b31 100644 --- a/spec/.hidden/.busted +++ b/spec/.hidden/.busted @@ -1,5 +1,9 @@ return { + _all = { + ['ROOT'] = {'tests'}, + }, default = { + ['ROOT'] = {'specs'}, ['tags'] = {'tag11','tag22','tag33'}, ['exclude-tags'] = {'etag11','etag22','etag33'}, ['pattern'] = '_spec%.lua$', diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index e845792c..629ce40f 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -217,7 +217,7 @@ describe('Tests using .busted tasks', function() local args = cli:parse({ '--directory=spec/.hidden' }) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) - assert.is_same({'spec'}, args.ROOT) + assert.is_same({'specs'}, args.ROOT) assert.is_equal('spec/.hidden', args.C) assert.is_equal('spec/.hidden', args.directory) assert.is_equal('_spec', args.p) @@ -262,6 +262,7 @@ describe('Tests using .busted tasks', function() local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden', '--run=test' }) assert.is_equal('_test%.lua$', args.pattern) + assert.is_same({'tests'}, args.ROOT) assert.is_same({'test1', 'test2', 'test3'}, args.tags) assert.is_same({'etest1', 'etest2', 'etest3'}, args['exclude-tags']) assert.is_same({'-s','--sound'}, args.Xoutput) diff --git a/spec/modules/configuration_loader_spec.lua b/spec/modules/configuration_loader_spec.lua index c5de45b1..104e0bc0 100644 --- a/spec/modules/configuration_loader_spec.lua +++ b/spec/modules/configuration_loader_spec.lua @@ -4,6 +4,9 @@ describe('Config Loader', function() before_each(function() testConfig = { + _all = { + other = 'stuff', + }, default = { output = 'utfTerminal' }, @@ -27,7 +30,8 @@ describe('Config Loader', function() it('returns a valid config with default config', function() local config, err = configLoader(testConfig, cliArgs) - assert.are.same(testConfig.default, config) + assert.are.same(testConfig.default.output, config.output) + assert.are.same(testConfig._all.other, config.other) assert.are.equal(nil, err) end) @@ -36,6 +40,7 @@ describe('Config Loader', function() local config, err = configLoader(testConfig, cliArgs) assert.are.same(testConfig.windows.output, config.output) + assert.are.same(testConfig._all.other, config.other) assert.are.equal(nil, err) end) @@ -45,6 +50,7 @@ describe('Config Loader', function() local config, err = configLoader(testConfig, cliArgs, defaults) assert.are.same(testConfig.windows.output, config.output) + assert.are.same(testConfig._all.other, config.other) assert.are.equal(nil, err) end) @@ -52,7 +58,8 @@ describe('Config Loader', function() cliArgs = { output = 'TAP' } local config, err = configLoader(testConfig, cliArgs, defaults) - assert.are.same(cliArgs, config) + assert.are.same(cliArgs.output, config.output) + assert.are.same(testConfig._all.other, config.other) assert.are.equal(nil, err) end) From 3777c725e00e3a06758503731a464b92ea8e1325 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 25 Mar 2015 22:14:35 -0700 Subject: [PATCH 193/293] Remove busted argument from output handlers No longer need to pass the `busted` object to any output handlers. They can use `require 'busted'` to get access to the any `busted` specific functionality. Everything needed by the output handlers should be available throught the exported busted API. --- busted/modules/filter_loader.lua | 2 +- busted/modules/helper_loader.lua | 2 +- busted/modules/output_handler_loader.lua | 4 ++-- busted/outputHandlers/TAP.lua | 5 +++-- busted/outputHandlers/base.lua | 7 ++++--- busted/outputHandlers/json.lua | 5 +++-- busted/outputHandlers/junit.lua | 5 +++-- busted/outputHandlers/plainTerminal.lua | 7 +++++-- busted/outputHandlers/sound.lua | 5 +++-- busted/outputHandlers/utfTerminal.lua | 7 +++++-- busted/runner.lua | 8 ++++---- spec/cl_output_handler.lua | 5 +++-- 12 files changed, 37 insertions(+), 25 deletions(-) diff --git a/busted/modules/filter_loader.lua b/busted/modules/filter_loader.lua index 98a0fa5d..1d54b485 100644 --- a/busted/modules/filter_loader.lua +++ b/busted/modules/filter_loader.lua @@ -1,5 +1,5 @@ return function() - local function filter(options, busted) + local function filter(busted, options) local getFullName = function(name) local parent = busted.context.get() local names = { name } diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index 1559abe1..17cde472 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -2,7 +2,7 @@ local utils = require 'busted.utils' local hasMoon, moonscript = pcall(require, 'moonscript') return function() - local loadHelper = function(helper, options, busted) + local loadHelper = function(busted, helper, options) local old_arg = arg local success, err = pcall(function() arg = options.arguments diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index 71f244f5..c507c460 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -2,7 +2,7 @@ local utils = require 'busted.utils' local hasMoon, moonscript = pcall(require, 'moonscript') return function() - local loadOutputHandler = function(output, options, busted, defaultOutput) + local loadOutputHandler = function(busted, output, options, defaultOutput) local handler local success, err = pcall(function() @@ -24,7 +24,7 @@ return function() handler = require('busted.outputHandlers.' .. defaultOutput) end - return handler(options, busted) + return handler(options) end return loadOutputHandler diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index 08ead59f..4d5775e9 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -1,7 +1,8 @@ local pretty = require 'pl.pretty' -return function(options, busted) - local handler = require 'busted.outputHandlers.base'(busted) +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() handler.suiteEnd = function() local total = handler.successesCount + handler.errorsCount + handler.failuresCount diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 67b7aa63..13da5148 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -1,4 +1,5 @@ -return function(busted) +return function() + local busted = require 'busted' local handler = { successes = {}, successesCount = 0, @@ -36,14 +37,14 @@ return function(busted) end handler.getFullName = function(context) - local parent = busted.context.parent(context) + local parent = busted.parent(context) local names = { (context.name or context.descriptor) } while parent and (parent.name or parent.descriptor) and parent.descriptor ~= 'file' do table.insert(names, 1, parent.name or parent.descriptor) - parent = busted.context.parent(parent) + parent = busted.parent(parent) end return table.concat(names, ' ') diff --git a/busted/outputHandlers/json.lua b/busted/outputHandlers/json.lua index f19a336a..08b87e0a 100644 --- a/busted/outputHandlers/json.lua +++ b/busted/outputHandlers/json.lua @@ -1,7 +1,8 @@ local json = require 'dkjson' -return function(options, busted) - local handler = require 'busted.outputHandlers.base'(busted) +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() handler.suiteEnd = function() print(json.encode({ diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index f6666515..ea851c9c 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -2,8 +2,9 @@ local xml = require 'pl.xml' local socket = require("socket") local string = require("string") -return function(options, busted) - local handler = require 'busted.outputHandlers.base'(busted) +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() local top = { start_time = socket.gettime(), xml_doc = xml.new('testsuites', { diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index c74cb76d..ac6a4226 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -1,8 +1,9 @@ local s = require 'say' local pretty = require 'pl.pretty' -return function(options, busted) - local handler = require 'busted.outputHandlers.base'(busted) +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() local successDot = '+' local failureDot = '-' @@ -132,6 +133,8 @@ return function(options, busted) local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') io.write(runString:format(count, total)) io.flush() + + return nil, true end handler.suiteEnd = function() diff --git a/busted/outputHandlers/sound.lua b/busted/outputHandlers/sound.lua index 8ac1a46c..8a749693 100644 --- a/busted/outputHandlers/sound.lua +++ b/busted/outputHandlers/sound.lua @@ -1,6 +1,7 @@ local app = require 'pl.app' -return function(options, busted) - local handler = require 'busted.outputHandlers.base'(busted) +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() local language = require('busted.languages.' .. options.language) handler.suiteEnd = function() diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 4f2b1c42..d04b51a5 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -10,8 +10,9 @@ else colors = require 'term.colors' end -return function(options, busted) - local handler = require 'busted.outputHandlers.base'(busted) +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() local successDot = colors.green('●') local failureDot = colors.red('◼') @@ -141,6 +142,8 @@ return function(options, busted) local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') io.write(runString:format(count, total)) io.flush() + + return nil, true end handler.suiteEnd = function(count, total) diff --git a/busted/runner.lua b/busted/runner.lua index e2327be9..e5436e56 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -115,11 +115,11 @@ return function(options) arguments = cliArgs.Xoutput } - local outputHandler = outputHandlerLoader(cliArgs.output, outputHandlerOptions, busted, options.defaultOutput) + local outputHandler = outputHandlerLoader(busted, cliArgs.output, outputHandlerOptions, options.defaultOutput) outputHandler:subscribe(outputHandlerOptions) if cliArgs['enable-sound'] then - require 'busted.outputHandlers.sound'(outputHandlerOptions, busted) + require 'busted.outputHandlers.sound'(outputHandlerOptions) end -- Set up randomization options @@ -138,7 +138,7 @@ return function(options) } -- Load tag and test filters - filterLoader(filterLoaderOptions, busted) + filterLoader(busted, filterLoaderOptions) -- Set up helper script if cliArgs.helper and cliArgs.helper ~= '' then @@ -148,7 +148,7 @@ return function(options) arguments = cliArgs.Xhelper } - helperLoader(cliArgs.helper, helperOptions, busted) + helperLoader(busted, cliArgs.helper, helperOptions) end -- Set up test loader options diff --git a/spec/cl_output_handler.lua b/spec/cl_output_handler.lua index 2c213813..b0fb48f0 100644 --- a/spec/cl_output_handler.lua +++ b/spec/cl_output_handler.lua @@ -1,7 +1,8 @@ -- supporting testfile; belongs to 'cl_spec.lua' -return function(options, busted) - local handler = require 'busted.outputHandlers.base'(busted) +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() local cli = require 'cliargs' local args = options.arguments From 6b4313a82366358fea0aaf28cdf07bb62ea19073 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 26 Mar 2015 13:04:44 -0700 Subject: [PATCH 194/293] Refactor test file loader options --- busted/modules/test_file_loader.lua | 14 +++++++------- busted/runner.lua | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 7eb56f60..43af5c77 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -1,6 +1,6 @@ local s = require 'say' -return function(busted, loaders, options) +return function(busted, loaders) local path = require 'pl.path' local dir = require 'pl.dir' local tablex = require 'pl.tablex' @@ -12,7 +12,7 @@ return function(busted, loaders, options) fileLoaders[#fileLoaders+1] = loader end - local getTestFiles = function(rootFile, pattern) + local getTestFiles = function(rootFile, pattern, options) local fileList if path.isfile(rootFile) then @@ -39,10 +39,10 @@ return function(busted, loaders, options) return fileList end - local getAllTestFiles = function(rootFiles, pattern) + local getAllTestFiles = function(rootFiles, pattern, options) local fileList = {} for _, root in ipairs(rootFiles) do - tablex.insertvalues(fileList, getTestFiles(root, pattern)) + tablex.insertvalues(fileList, getTestFiles(root, pattern, options)) end return fileList end @@ -56,8 +56,8 @@ return function(busted, loaders, options) end end - local loadTestFiles = function(rootFiles, pattern, loaders) - local fileList = getAllTestFiles(rootFiles, pattern) + local loadTestFiles = function(rootFiles, pattern, options) + local fileList = getAllTestFiles(rootFiles, pattern, options) if options.shuffle then shuffle(fileList, options.seed) @@ -66,7 +66,7 @@ return function(busted, loaders, options) end for i, fileName in ipairs(fileList) do - local testFile, getTrace, rewriteMessage = loadTestFile(busted, fileName, loaders) + local testFile, getTrace, rewriteMessage = loadTestFile(busted, fileName) if testFile then local file = setmetatable({ diff --git a/busted/runner.lua b/busted/runner.lua index e2327be9..e7c3634c 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -163,8 +163,8 @@ return function(options) -- Load test directory local rootFiles = cliArgs.ROOT or { fileName } local pattern = cliArgs.pattern - local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders, testFileLoaderOptions) - local fileList = testFileLoader(rootFiles, pattern) + local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) + local fileList = testFileLoader(rootFiles, pattern, testFileLoaderOptions) if not cliArgs.ROOT then local ctx = busted.context.get() From 719d93b6dfe7aea09d96c59736784800fcd93a28 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 26 Mar 2015 13:47:34 -0700 Subject: [PATCH 195/293] Support disabling randomization in context blocks This adds a `norandomize` function to file and describe contexts so that test randomization within the current context block can be explicitly disabled, overriding any command-line flags to enable randomization. --- busted/block.lua | 2 ++ spec/core_spec.lua | 4 +++- spec/randomize_spec.lua | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/busted/block.lua b/busted/block.lua index fc2609b1..c51b5f42 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -26,6 +26,7 @@ return function(busted) function block.rejectAll(element) block.reject('randomize', element) + block.reject('norandomize', element) for descriptor, _ in pairs(busted.executors) do block.reject(descriptor, element) end @@ -135,6 +136,7 @@ return function(busted) local randomize = busted.randomize element.env.randomize = function() randomize = true end + element.env.norandomize = function() randomize = false end if busted.safe(descriptor, element.run, element):success() then if randomize then diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 9d61bbbf..08a542c7 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -368,8 +368,9 @@ describe('tests unsupported functions', function() assert.has_error(strict_teardown, "'strict_teardown' not supported inside current context block") end) - it('it block throws error on randomize', function() + it('it block throws error on randomize/norandomize', function() assert.has_error(randomize, "'randomize' not supported inside current context block") + assert.has_error(norandomize, "'norandomize' not supported inside current context block") end) it('finaly block throws error on pending', function() @@ -384,6 +385,7 @@ describe('tests unsupported functions in setup/before_each/after_each/teardown', assert.is_nil(file) assert.is_nil(finally) assert.has_error(randomize, "'randomize' not supported inside current context block") + assert.has_error(norandomize, "'norandomize' not supported inside current context block") assert.has_error(describe, "'describe' not supported inside current context block") assert.has_error(context, "'context' not supported inside current context block") diff --git a/spec/randomize_spec.lua b/spec/randomize_spec.lua index 55208a81..2fa6e014 100644 --- a/spec/randomize_spec.lua +++ b/spec/randomize_spec.lua @@ -18,3 +18,23 @@ describe('Order of tests ran', function() assert.are_not.same(unexpected, order) end) end) + +describe('Disabling randomized test order', function() + randomize() + norandomize() + + local expected = {} + local order = {} + + for i = 1, 100 do + table.insert(expected, i) + + it('does 100 its', function() + table.insert(order, i) + end) + end + + it('does not randomize tests', function() + assert.are.same(expected, order) + end) +end) From b3b99845331e5a944d0e77140ca55f5fc59bb1c0 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 26 Mar 2015 13:05:06 -0700 Subject: [PATCH 196/293] Fix for running tests standalone This updates the standalone run mode to use the last child of the root context as the 'file' descriptor, instead of assuming the first child in the root context is the 'file' descriptor. A helper script could add support functions to the root context (e.g. 'setup'/'teardown'/etc), so the first child may not be a 'file' descriptor, but the last child will always be a 'file' descriptor since the test file was just loaded prior to the standalone test file setup for live coding. --- busted/execute.lua | 2 +- busted/runner.lua | 4 +++- spec/cl_spec.lua | 9 +++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/busted/execute.lua b/busted/execute.lua index 2132d8ef..3fbb3384 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -13,7 +13,7 @@ return function(busted) ctx[k] = v end - for _, child in pairs(children) do + for _, child in ipairs(children) do for descriptor, _ in pairs(busted.executors) do child[descriptor] = nil end diff --git a/busted/runner.lua b/busted/runner.lua index e7c3634c..2c4aa143 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -166,9 +166,11 @@ return function(options) local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) local fileList = testFileLoader(rootFiles, pattern, testFileLoaderOptions) + -- If running standalone, setup test file to be compatible with live coding if not cliArgs.ROOT then local ctx = busted.context.get() - local file = busted.context.children(ctx)[1] + local children = busted.context.children(ctx) + local file = children[#children] getmetatable(file.run).__call = info.func end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index e127b5b5..cec45e9d 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -347,6 +347,15 @@ describe('Test busted running standalone', function() error_end() end) + it('tests running with --helper specified', function () + local success, exitcode + error_start() + success, exitcode = execute('lua spec/cl_standalone.lua --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown,--fail-after-each"') + assert.is_false(success) + assert.is_equal(9, exitcode) + error_end() + end) + it('tests running with --version specified', function() local success, exitcode success, exitcode = execute('lua spec/cl_standalone.lua --version') From e8c09dcbe6e9a8bb1f4dad64ed80459d901ce0f4 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 23 Mar 2015 22:44:17 -0700 Subject: [PATCH 197/293] Support `--no-flags` to disable features This allows flags to be enabled and later disabled on the same command-line. This change also allows a flag to be enabled in a .busted task, and later disabled on the command-line. --- busted/modules/cli.lua | 34 +++++----- busted/runner.lua | 8 +-- completions/bash/busted.bash | 20 +++--- completions/zsh/_busted | 42 ++++++++---- spec/modules/cli_spec.lua | 128 ++++++++++++++++++++++++----------- 5 files changed, 150 insertions(+), 82 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index b2ca0454..18d07af4 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -96,7 +96,7 @@ return function(options) end -- Load up the command-line interface options - cli:add_flag('--version', 'prints the program version and exits', processOption) + cli:add_flag('--version', 'prints the program version and exits', false, processOption) if options.batch then cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 999, processArgList) @@ -122,22 +122,22 @@ return function(options) cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) - cli:add_flag('-c, --coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', processOption) - cli:add_flag('-v, --verbose', 'verbose output of errors', processOption) - cli:add_flag('-s, --enable-sound', 'executes `say` command if available', processOption) - cli:add_flag('-l, --list', 'list the names of all tests instead of running them', processOption) - cli:add_flag('--lazy', 'use lazy setup/teardown as the default', processOption) - cli:add_flag('--no-auto-insulate', 'disable file insulation', processOption) - cli:add_flag('--no-keep-going', 'quit after first error or failure', processOption) - cli:add_flag('--no-recursive', 'do not recurse into subdirectories', processOption) - cli:add_flag('--shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processOption) - cli:add_flag('--shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) - cli:add_flag('--shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) - cli:add_flag('--sort', 'sort file and test order (--sort-tests and --sort-files)', processOption) - cli:add_flag('--sort-files', 'sort file execution order', processOption) - cli:add_flag('--sort-tests', 'sort test order within a file', processOption) - cli:add_flag('--suppress-pending', 'suppress `pending` test output', processOption) - cli:add_flag('--defer-print', 'defer print to when test suite is complete', processOption) + cli:add_flag('-c, --[no-]coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', false, processOption) + cli:add_flag('-v, --[no-]verbose', 'verbose output of errors', false, processOption) + cli:add_flag('-s, --[no-]enable-sound', 'executes `say` command if available', false, processOption) + cli:add_flag('-l, --list', 'list the names of all tests instead of running them', false, processOption) + cli:add_flag('--[no-]lazy', 'use lazy setup/teardown as the default', false, processOption) + cli:add_flag('--[no-]auto-insulate', 'enable file insulation', true, processOption) + cli:add_flag('-k, --[no-]keep-going', 'continue as much as possible after an error or failure', true, processOption) + cli:add_flag('-R, --[no-]recursive', 'recurse into subdirectories', true, processOption) + cli:add_flag('--[no-]shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', false, processOption) + cli:add_flag('--[no-]shuffle-files', 'randomize file execution order, takes precedence over --sort-files', false, processOption) + cli:add_flag('--[no-]shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', false, processOption) + cli:add_flag('--[no-]sort', 'sort file and test order (--sort-tests and --sort-files)', false, processOption) + cli:add_flag('--[no-]sort-files', 'sort file execution order', false, processOption) + cli:add_flag('--[no-]sort-tests', 'sort test order within a file', false, processOption) + cli:add_flag('--[no-]suppress-pending', 'suppress `pending` test output', false, processOption) + cli:add_flag('--[no-]defer-print', 'defer print to when test suite is complete', false, processOption) local function parse(args) -- Parse the cli arguments diff --git a/busted/runner.lua b/busted/runner.lua index e2327be9..4225cf96 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -56,7 +56,7 @@ return function(options) end -- If auto-insulate is disabled, re-register file without insulation - if cliArgs['no-auto-insulate'] then + if not cliArgs['auto-insulate'] then busted.register('file', 'file', {}) end @@ -78,7 +78,7 @@ return function(options) -- watch for test errors and failures local failures = 0 local errors = 0 - local quitOnError = cliArgs['no-keep-going'] + local quitOnError = not cliArgs['keep-going'] busted.subscribe({ 'error', 'output' }, function(element, parent, message) io.stderr:write(appName .. ': error: Cannot load output library: ' .. element.name .. '\n' .. message .. '\n') @@ -134,7 +134,7 @@ return function(options) filter = cliArgs.filter, filterOut = cliArgs['filter-out'], list = cliArgs.list, - nokeepgoing = cliArgs['no-keep-going'], + nokeepgoing = not cliArgs['keep-going'], } -- Load tag and test filters @@ -156,7 +156,7 @@ return function(options) verbose = cliArgs.verbose, sort = cliArgs['sort-files'] or cliArgs.sort, shuffle = cliArgs['shuffle-files'] or cliArgs.shuffle, - recursive = not cliArgs['no-recursive'], + recursive = cliArgs['recursive'], seed = busted.randomseed } diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index b21838d2..2d72a122 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -135,7 +135,7 @@ _busted() { if [[ "${cur}" == -* ]] ; then local opts=" -h --help - -v --verbose + -v --verbose --no-verbose --version -l --list -o --output= @@ -150,18 +150,20 @@ _busted() { --lang= --loaders= --helper= - -c --coverage - -s --enable-sound + -c --coverage --no-coverage + -s --enable-sound --no-enable-sound -Xoutput -Xhelper - --lazy - --no-auto-insulate - --no-keep-going - --no-recursive + --lazy --no-lazy + --auto-insulate --no-auto-insulate + -k --keep-going --no-keep-going + -R --recursive --no-recursive --shuffle --shuffle-tests --shuffle-files + --no-shuffle --no-shuffle-tests --no-shuffle-files --sort --sort-tests --sort-files - --supress-pending - --defer-print" + --no-sort --no-sort-tests --no-sort-files + --supress-pending --no-supress-pending + --defer-print --no-defer-print" compopt -o nospace local IFS=$'\n' diff --git a/completions/zsh/_busted b/completions/zsh/_busted index b557309d..4fd2898f 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -6,28 +6,41 @@ local _busted_args _busted_args=( "--cpath=[Optional path to be prefixed to the Lua C module search path (default: ./csrc/?.so;./csrc/?/?.so;)]:directory:_dirs" -"--defer-print[Defer print to when test suite is complete]" +"(--defer-print --no-defer-print)--defer-print[Defer print to when test suite is complete]" +"(--defer-print --no-defer-print)--no-defer-print[Do not defer print to when test suite is complete]" "--lang=[Language for error messages (default: en)]:languages:(ar de en fr ja nl ru th ua zh)" "--repeat=[Run the tests repeatedly (default: 1)]: :" "--seed=[Random seed value to use for shuffing test order (default: os.time())]: :" -"(--sort --shuffle)--shuffle[Randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)]" -"(--sort-files --shuffle-files)--shuffle-files[Randomize file execution order, takes precedence over --sort-files]" -"(--sort-tests --shuffle-tests)--shuffle-tests[Randomize test order within a file, takes precedence over --sort-tests]" -"(--sort --shuffle)--sort[Sort file and test order (--sort-tests and --sort-files)]" -"(--sort-files --shuffle-files)--sort-files[Sort file execution order]" -"(--sort-tests --shuffle-tests)--sort-tests[Sort test order within a file]" -"--suppress-pending[Suppress 'pending' test output]" +"(--sort --shuffle --no-shuffle --no-sort)--shuffle[Randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)]" +"(--sort --shuffle --no-shuffle --no-sort)--no-shuffle[Do not randomize file and test order]" +"(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--shuffle-files[Randomize file execution order, takes precedence over --sort-files]" +"(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--no-shuffle-files[Do not randomize file execution order]" +"(--sort-tests --shuffle-tests --no-sort-tests --no-shuffle-tests)--shuffle-tests[Randomize test order within a file, takes precedence over --sort-tests]" +"(--sort-tests --shuffle-tests --no-sort-tests --no-shuffle-tests)--no-shuffle-tests[Do not randomize test order within a file]" +"(--sort --shuffle --no-shuffle --no-sort)--sort[Sort file and test order (--sort-tests and --sort-files)]" +"(--sort --shuffle --no-shuffle --no-sort)--no-sort[Do not sort file and test order]" +"(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--sort-files[Sort file execution order]" +"(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--no-sort-files[Do not sort file execution order]" +"(--sort-tests --shuffle-tests --no-sort-tests --no-shuffle-tests)--sort-tests[Sort test order within a file]" +"(--sort-tests --shuffle-tests --no-sort-tests --no-shuffle-tests)--no-sort-tests[Do not sort test order within a file]" +"(--suppress-pending --no-suppress-pending)--suppress-pending[Suppress 'pending' test output]" +"(--suppress-pending --no-suppress-pending)--no-suppress-pending[Do not suppress 'pending' test output]" "--version[Prints the program version and exits]" "(-l --list)"{-l,--list}"[List the names of all tests instead of running them]" -"--lazy[Use lazy setup/teardown as the default]" -"--no-auto-insulate[Disable file insulation]" -"--no-keep-going[Quit after first error or failure]" -"--no-recursive[Do not recurse into subdirectories]" +"(--lazy --no-lazy)--lazy[Use lazy setup/teardown as the default]" +"(--lazy --no-lazy)--no-lazy[Use strict setup/teardown as the default]" +"(--auto-insulate --no-auto-insulate)--auto-insulate[Enable file insulation]" +"(--auto-insulate --no-auto-insulate)--no-auto-insulate[Disable file insulation]" +"(-k --keep-going --no-keep-going)--keep-going[Continue as much as possible after an error or failure]" +"(-k --keep-going --no-keep-going)--no-keep-going[Quit after first error or failure]" +"(-R --recursive --no-recursive)--recursive[Recurse into subdirectories]" +"(-R --recursive --no-recursive)--no-recursive[Do not recurse into subdirectories]" "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" "-Xoutput[Pass 'OPTION' as an option to the output handler. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" "-Xhelper[Pass 'OPTION' as an option to the helper script. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" -"(-c --coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" +"(-c --coverage --no-coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" +"(-c --coverage --no-coverage)--no-coverage[Disable code coverage analysis]" "(-C --directory)"{-C,--directory=}"[Change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one. (default: ./)]:directory:_dirs" "(-h --help)"{-h,--help}"[Help]" "(-m --lpath)"{-m,--lpath=}"[Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua)]:directory:_dirs" @@ -39,7 +52,8 @@ _busted_args=( "--exclude-tags=[Do not run tests with these #tags, takes precedence over --tags]: :" "--filter=[Only run test names matching the Lua pattern]: :" "--filter-out=[Do not run test names matching the Lua pattern, takes precedence over --filter]: :" -"(-v --verbose)"{-v,--verbose}"[Verbose output of errors]" +"(-v --verbose --no-verbose)"{-v,--verbose}"[Verbose output of errors]" +"(-v --verbose --no-verbose)--no-verbose[Disable verbose output of errors]" "*:files:_files" ) diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 629ce40f..a75ff522 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -20,23 +20,27 @@ describe('Tests command-line interface', function() assert.is_equal(lpath, args.m) assert.is_equal(lpath, args.lpath) assert.is_equal(cpath, args.cpath) - assert.is_nil(args.c) - assert.is_nil(args.coverage) - assert.is_nil(args.version) - assert.is_nil(args.v) - assert.is_nil(args.verbose) - assert.is_nil(args.l) - assert.is_nil(args.list) - assert.is_nil(args.s) - assert.is_nil(args['enable-sound']) - assert.is_nil(args['no-keep-going']) - assert.is_nil(args['no-recursive']) - assert.is_nil(args['suppress-pending']) - assert.is_nil(args['defer-print']) - assert.is_nil(args.shuffle) - assert.is_nil(args['shuffle-files']) - assert.is_nil(args.sort) - assert.is_nil(args['sort-files']) + assert.is_true(args['auto-insulate']) + assert.is_true(args.k) + assert.is_true(args['keep-going']) + assert.is_true(args.R) + assert.is_true(args['recursive']) + assert.is_false(args.c) + assert.is_false(args.coverage) + assert.is_false(args.version) + assert.is_false(args.v) + assert.is_false(args.verbose) + assert.is_false(args.l) + assert.is_false(args.list) + assert.is_false(args.lazy) + assert.is_false(args.s) + assert.is_false(args['enable-sound']) + assert.is_false(args['suppress-pending']) + assert.is_false(args['defer-print']) + assert.is_false(args.shuffle) + assert.is_false(args['shuffle-files']) + assert.is_false(args.sort) + assert.is_false(args['sort-files']) assert.is_nil(args.r) assert.is_nil(args.run) assert.is_nil(args.helper) @@ -71,13 +75,41 @@ describe('Tests command-line interface', function() it('specify more flags', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '-s', '--list', '--no-keep-going', '--no-recursive' }) + local args = cli:parse({ '-s', '--list', '-k', '--no-keep-going', '-R', '--no-recursive' }) assert.is_true(args.s) assert.is_true(args['enable-sound']) assert.is_true(args.l) assert.is_true(args.list) - assert.is_true(args['no-keep-going']) - assert.is_true(args['no-recursive']) + assert.is_false(args['keep-going']) + assert.is_false(args['recursive']) + end) + + it('specify even more flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--lazy', '--no-auto-insulate', '-k', '-R' }) + assert.is_true(args.lazy) + assert.is_false(args['auto-insulate']) + assert.is_true(args.k) + assert.is_true(args['keep-going']) + assert.is_true(args.R) + assert.is_true(args.recursive) + end) + + it('specify no-flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--no-lazy', '--no-auto-insulate', '--no-coverage', '--no-verbose' }) + assert.is_false(args.lazy) + assert.is_false(args['auto-insulate']) + assert.is_false(args.coverage) + assert.is_false(args.verbose) + end) + + it('specify more no-flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--no-enable-sound', '--no-suppress-pending', '--no-defer-print' }) + assert.is_false(args['enable-sound']) + assert.is_false(args['suppress-pending']) + assert.is_false(args['defer-print']) end) it('specify shuffle flags', function() @@ -88,7 +120,15 @@ describe('Tests command-line interface', function() assert.is_true(args['shuffle-tests']) end) - it('specify short flags', function() + it('specify shuffle no-flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--no-shuffle', '--no-shuffle-files', '--no-shuffle-tests' }) + assert.is_false(args.shuffle) + assert.is_false(args['shuffle-files']) + assert.is_false(args['shuffle-tests']) + end) + + it('specify sort flags', function() local cli = require 'busted.modules.cli'() local args = cli:parse({ '--sort', '--sort-files', '--sort-tests' }) assert.is_true(args.sort) @@ -96,6 +136,14 @@ describe('Tests command-line interface', function() assert.is_true(args['sort-tests']) end) + it('specify sort no-flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--no-sort', '--no-sort-files', '--no-sort-tests' }) + assert.is_false(args.sort) + assert.is_false(args['sort-files']) + assert.is_false(args['sort-tests']) + end) + it('specify ROOT arg and --pattern', function() local cli = require 'busted.modules.cli'({ batch = true }) local args = cli:parse({ '-p', 'match_files', 'root_is_here' }) @@ -228,23 +276,27 @@ describe('Tests using .busted tasks', function() assert.is_equal(lpath, args.m) assert.is_equal(lpath, args.lpath) assert.is_equal(cpath, args.cpath) - assert.is_nil(args.c) - assert.is_nil(args.coverage) - assert.is_nil(args.version) - assert.is_nil(args.v) - assert.is_nil(args.verbose) - assert.is_nil(args.l) - assert.is_nil(args.list) - assert.is_nil(args.s) - assert.is_nil(args['enable-sound']) - assert.is_nil(args['no-keep-going']) - assert.is_nil(args['no-recursive']) - assert.is_nil(args['suppress-pending']) - assert.is_nil(args['defer-print']) - assert.is_nil(args.shuffle) - assert.is_nil(args['shuffle-files']) - assert.is_nil(args.sort) - assert.is_nil(args['sort-files']) + assert.is_true(args['auto-insulate']) + assert.is_true(args.k) + assert.is_true(args['keep-going']) + assert.is_true(args.R) + assert.is_true(args['recursive']) + assert.is_false(args.c) + assert.is_false(args.coverage) + assert.is_false(args.version) + assert.is_false(args.v) + assert.is_false(args.verbose) + assert.is_false(args.l) + assert.is_false(args.list) + assert.is_false(args.lazy) + assert.is_false(args.s) + assert.is_false(args['enable-sound']) + assert.is_false(args['suppress-pending']) + assert.is_false(args['defer-print']) + assert.is_false(args.shuffle) + assert.is_false(args['shuffle-files']) + assert.is_false(args.sort) + assert.is_false(args['sort-files']) assert.is_nil(args.r) assert.is_nil(args.run) assert.is_nil(args.helper) From 4ef7c412d7db35087822853ab212e6668e82e2ca Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 23 Mar 2015 23:26:39 -0700 Subject: [PATCH 198/293] Update `--shuffle` and `--sort` command-line flags This allows the `--shuffle` and `--sort` command-line flags to function as aliases for `--shuffle-files --shuffle-tests` and `--sort-files --sort-tests`, respectively. Similarly, `--no-shuffle` and `--no-sort` function as alias for `--no-shufle-files --no-shuffle-tests` and `--no-sort-files --no-sort-tests`, respectively. --- busted/modules/cli.lua | 22 ++++++++---- busted/runner.lua | 8 ++--- completions/zsh/_busted | 4 +-- spec/modules/cli_spec.lua | 72 +++++++++++++++++++++++++++++++++------ 4 files changed, 84 insertions(+), 22 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 18d07af4..9749149d 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -95,6 +95,16 @@ return function(options) return true end + local function processShuffle(key, value, altkey, opt) + processOption('shuffle-files', value, nil, opt) + processOption('shuffle-tests', value, nil, opt) + end + + local function processSort(key, value, altkey, opt) + processOption('sort-files', value, nil, opt) + processOption('sort-tests', value, nil, opt) + end + -- Load up the command-line interface options cli:add_flag('--version', 'prints the program version and exits', false, processOption) @@ -130,12 +140,12 @@ return function(options) cli:add_flag('--[no-]auto-insulate', 'enable file insulation', true, processOption) cli:add_flag('-k, --[no-]keep-going', 'continue as much as possible after an error or failure', true, processOption) cli:add_flag('-R, --[no-]recursive', 'recurse into subdirectories', true, processOption) - cli:add_flag('--[no-]shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', false, processOption) - cli:add_flag('--[no-]shuffle-files', 'randomize file execution order, takes precedence over --sort-files', false, processOption) - cli:add_flag('--[no-]shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', false, processOption) - cli:add_flag('--[no-]sort', 'sort file and test order (--sort-tests and --sort-files)', false, processOption) - cli:add_flag('--[no-]sort-files', 'sort file execution order', false, processOption) - cli:add_flag('--[no-]sort-tests', 'sort test order within a file', false, processOption) + cli:add_flag('--[no-]shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processShuffle) + cli:add_flag('--[no-]shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) + cli:add_flag('--[no-]shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) + cli:add_flag('--[no-]sort', 'sort file and test order (--sort-tests and --sort-files)', processSort) + cli:add_flag('--[no-]sort-files', 'sort file execution order', processOption) + cli:add_flag('--[no-]sort-tests', 'sort test order within a file', processOption) cli:add_flag('--[no-]suppress-pending', 'suppress `pending` test output', false, processOption) cli:add_flag('--[no-]defer-print', 'defer print to when test suite is complete', false, processOption) diff --git a/busted/runner.lua b/busted/runner.lua index 4225cf96..796d651b 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -123,8 +123,8 @@ return function(options) end -- Set up randomization options - busted.sort = cliArgs['sort-tests'] or cliArgs.sort - busted.randomize = cliArgs['shuffle-tests'] or cliArgs.shuffle + busted.sort = cliArgs['sort-tests'] + busted.randomize = cliArgs['shuffle-tests'] busted.randomseed = tonumber(cliArgs.seed) or os.time() -- Set up tag and test filter options @@ -154,8 +154,8 @@ return function(options) -- Set up test loader options local testFileLoaderOptions = { verbose = cliArgs.verbose, - sort = cliArgs['sort-files'] or cliArgs.sort, - shuffle = cliArgs['shuffle-files'] or cliArgs.shuffle, + sort = cliArgs['sort-files'], + shuffle = cliArgs['shuffle-files'], recursive = cliArgs['recursive'], seed = busted.randomseed } diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 4fd2898f..eaedf5d9 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -12,13 +12,13 @@ _busted_args=( "--repeat=[Run the tests repeatedly (default: 1)]: :" "--seed=[Random seed value to use for shuffing test order (default: os.time())]: :" "(--sort --shuffle --no-shuffle --no-sort)--shuffle[Randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)]" -"(--sort --shuffle --no-shuffle --no-sort)--no-shuffle[Do not randomize file and test order]" +"(--sort --shuffle --no-shuffle --no-sort)--no-shuffle[Do not randomize file and test order (--no-shuffle-test and --no-shuffle-files)]" "(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--shuffle-files[Randomize file execution order, takes precedence over --sort-files]" "(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--no-shuffle-files[Do not randomize file execution order]" "(--sort-tests --shuffle-tests --no-sort-tests --no-shuffle-tests)--shuffle-tests[Randomize test order within a file, takes precedence over --sort-tests]" "(--sort-tests --shuffle-tests --no-sort-tests --no-shuffle-tests)--no-shuffle-tests[Do not randomize test order within a file]" "(--sort --shuffle --no-shuffle --no-sort)--sort[Sort file and test order (--sort-tests and --sort-files)]" -"(--sort --shuffle --no-shuffle --no-sort)--no-sort[Do not sort file and test order]" +"(--sort --shuffle --no-shuffle --no-sort)--no-sort[Do not sort file and test order (--no-sort-tests and --no-sort-files)]" "(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--sort-files[Sort file execution order]" "(--sort-files --shuffle-files --no-sort-files --no-shuffle-files)--no-sort-files[Do not sort file execution order]" "(--sort-tests --shuffle-tests --no-sort-tests --no-shuffle-tests)--sort-tests[Sort test order within a file]" diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index a75ff522..d1815f46 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -37,10 +37,12 @@ describe('Tests command-line interface', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) - assert.is_false(args.shuffle) - assert.is_false(args['shuffle-files']) - assert.is_false(args.sort) - assert.is_false(args['sort-files']) + assert.is_nil(args.shuffle) + assert.is_nil(args['shuffle-files']) + assert.is_nil(args['shuffle-tests']) + assert.is_nil(args.sort) + assert.is_nil(args['sort-files']) + assert.is_nil(args['sort-tests']) assert.is_nil(args.r) assert.is_nil(args.run) assert.is_nil(args.helper) @@ -114,7 +116,15 @@ describe('Tests command-line interface', function() it('specify shuffle flags', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '--shuffle', '--shuffle-files', '--shuffle-tests' }) + local args = cli:parse({ '--shuffle-files', '--shuffle-tests' }) + assert.is_nil(args.shuffle) + assert.is_true(args['shuffle-files']) + assert.is_true(args['shuffle-tests']) + end) + + it('specify shuffle flag only', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--shuffle', }) assert.is_true(args.shuffle) assert.is_true(args['shuffle-files']) assert.is_true(args['shuffle-tests']) @@ -128,9 +138,33 @@ describe('Tests command-line interface', function() assert.is_false(args['shuffle-tests']) end) + it('specify no-shuffle flag only', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--no-shuffle', }) + assert.is_false(args.shuffle) + assert.is_false(args['shuffle-files']) + assert.is_false(args['shuffle-tests']) + end) + + it('specify shuffle and no-shuffle flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--shuffle', '--no-shuffle-files' }) + assert.is_true(args.shuffle) + assert.is_false(args['shuffle-files']) + assert.is_true(args['shuffle-tests']) + end) + it('specify sort flags', function() local cli = require 'busted.modules.cli'() - local args = cli:parse({ '--sort', '--sort-files', '--sort-tests' }) + local args = cli:parse({ '--sort-files', '--sort-tests' }) + assert.is_nil(args.sort) + assert.is_true(args['sort-files']) + assert.is_true(args['sort-tests']) + end) + + it('specify sort flag only', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--sort', }) assert.is_true(args.sort) assert.is_true(args['sort-files']) assert.is_true(args['sort-tests']) @@ -144,6 +178,22 @@ describe('Tests command-line interface', function() assert.is_false(args['sort-tests']) end) + it('specify no-sort flag only', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--no-sort', }) + assert.is_false(args.sort) + assert.is_false(args['sort-files']) + assert.is_false(args['sort-tests']) + end) + + it('specify sort and no-sort flags', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '--sort', '--no-sort-files' }) + assert.is_true(args.sort) + assert.is_false(args['sort-files']) + assert.is_true(args['sort-tests']) + end) + it('specify ROOT arg and --pattern', function() local cli = require 'busted.modules.cli'({ batch = true }) local args = cli:parse({ '-p', 'match_files', 'root_is_here' }) @@ -293,10 +343,12 @@ describe('Tests using .busted tasks', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) - assert.is_false(args.shuffle) - assert.is_false(args['shuffle-files']) - assert.is_false(args.sort) - assert.is_false(args['sort-files']) + assert.is_nil(args.shuffle) + assert.is_nil(args['shuffle-files']) + assert.is_nil(args['shuffle-tests']) + assert.is_nil(args.sort) + assert.is_nil(args['sort-files']) + assert.is_nil(args['sort-tests']) assert.is_nil(args.r) assert.is_nil(args.run) assert.is_nil(args.helper) From 43f6a799d7f7f187bcf78e2052c8c25a779d219f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 26 Mar 2015 12:21:56 -0700 Subject: [PATCH 199/293] Update rockspec for --no-flags compatibility --- busted-2.0.rc7-0.rockspec | 2 +- busted-scm-0.rockspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index abd702c8..fc7cbf6c 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.4-1', + 'lua_cliargs >= 2.5-0', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 81fec3af..846dfef7 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.4-1', + 'lua_cliargs >= 2.5-0', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', From 10ce261ca7a405b7093f9e30b0a12b5cc25c06d7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 1 Apr 2015 13:29:59 -0700 Subject: [PATCH 200/293] Add command-line option to specify config file This allows the configuration task file to be explicity specified on the command-line instead of loading the .busted file in the current working directory. --- busted/modules/cli.lua | 3 +- completions/bash/busted.bash | 34 ++++++++++++++------ completions/zsh/_busted | 32 ++++++++++++------- spec/modules/cli_spec.lua | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 22 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 9749149d..11807ac6 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -116,6 +116,7 @@ return function(options) cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) cli:add_option('-C, --directory=DIR', 'change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) + cli:add_option('-f, --config-file=FILE', 'load configuration options from FILE', nil, processOptions) cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', {}, processMultiOption) @@ -158,7 +159,7 @@ return function(options) -- Load busted config file if available local configFile = { } - local bustedConfigFilePath = utils.normpath(path.join(cliArgs.directory, '.busted')) + local bustedConfigFilePath = cliArgs.f or utils.normpath(path.join(cliArgs.directory, '.busted')) local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) if bustedConfigFile then local config, err = configLoader(configFile, cliArgsParsed, cliArgs) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 2d72a122..faf86377 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -44,32 +44,41 @@ _busted() { ;; -r|--run) local d="." + local f local i local word for (( i=1; i < ${#COMP_WORDS[@]}-1; i++ )); do case "${COMP_WORDS[i]}" in - -C) + -C|-f) word="${COMP_WORDS[i+1]}" - if [ "${word:0:1}" == "/" ]; then - d="${word}" + if [ "${COMP_WORDS[i]}" == "-f" ]; then + f="${word}" else - d="${d}/${word}" + if [ "${word:0:1}" == "/" ]; then + d="${word}" + else + d="${d}/${word}" + fi fi ;; - --directory) + --directory|--config-file) word="${COMP_WORDS[i+1]}" if [ "${word}" == "=" ]; then word="${COMP_WORDS[i+2]}" fi - if [ "${word:0:1}" == "/" ]; then - d="${word}" + if [ "${COMP_WORDS[i]}" == "--config-file" ]; then + f="${word}" else - d="${d}/${word}" + if [ "${word:0:1}" == "/" ]; then + d="${word}" + else + d="${d}/${word}" + fi fi ;; esac done - local cfgs=$(lua -e "cfgs=dofile('${d}/.busted')" \ + local cfgs=$(lua -e "cfgs=dofile('${f:-${d}/.busted}')" \ -e "for k,_ in pairs(cfgs) do print(k) end" 2> /dev/null) COMPREPLY=( $(compgen -W "${cfgs}" -- ${cur}) ) return 0 @@ -98,6 +107,10 @@ _busted() { _filedir -d return 0 ;; + -f|--config-file) + _filedir + return 0 + ;; --helper) _filedir return 0 @@ -140,7 +153,8 @@ _busted() { -l --list -o --output= -p --pattern= - -C --Cwd= + -C --directory= + -f --config-file= -t --tags= --exclude-tags= -m --lpath= --cpath= -r --run= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index eaedf5d9..9ccdd025 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -42,6 +42,7 @@ _busted_args=( "(-c --coverage --no-coverage)"{-c,--coverage}"[Do code coverage analysis (requires 'LuaCov' to be installed)]" "(-c --coverage --no-coverage)--no-coverage[Disable code coverage analysis]" "(-C --directory)"{-C,--directory=}"[Change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one. (default: ./)]:directory:_dirs" +"(-f --config-file)"{-f,--config-file=}"[Load configuration options from FILE]:files:_files" "(-h --help)"{-h,--help}"[Help]" "(-m --lpath)"{-m,--lpath=}"[Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua)]:directory:_dirs" "(-o --output)"{-o,--output=}"[Output library to load (default: utfTerminal)]:output handlers:->output" @@ -65,31 +66,40 @@ _arguments -s $_busted_args case "${state}" in run) local d="." + local f local i local word for (( i=1; i < ${#words}; i++ )); do case "${words[i]}" in - -C|--directory) + -C|--directory|-f|--config-file) word="${words[i+1]}" - if [[ "${word[1,1]}" == "/" ]]; then - d="${word}" + if [[ "${words[i]}" == "-f" ]]; then + f="${word}" else - d="${d}/${word}" + if [[ "${word[1,1]}" == "/" ]]; then + d="${word}" + else + d="${d}/${word}" + fi fi ;; - --directory=*) - word="${words[i][7,-1]}" - if [[ "${word[1,1]}" == "/" ]]; then - d="${word}" + --directory=*|--config-file=*) + if [[ "${words[i][1,14]}" == "--config-file=" ]]; then + f="${words[i][15,-1]}" else - d="${d}/${word}" + word="${words[i][13,-1]}" + if [[ "${word[1,1]}" == "/" ]]; then + d="${word}" + else + d="${d}/${word}" + fi fi ;; esac done local cfgs - cfgs=$(lua -e "cfgs=dofile('${d}/.busted')" \ - -e "for k,_ in pairs(cfgs) do print(k) end" 2> /dev/null) + cfgs=$(lua -e "cfgs=dofile('${f:-${d}/.busted}')" \ + -e "for k,_ in pairs(cfgs) do print(k) end" 2> /dev/null) _arguments -s "*:run configurations:(${cfgs})" ;; output) diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index d1815f46..ae7576f5 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -37,6 +37,8 @@ describe('Tests command-line interface', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) + assert.is_nil(args.f) + assert.is_nil(args['config-file']) assert.is_nil(args.shuffle) assert.is_nil(args['shuffle-files']) assert.is_nil(args['shuffle-tests']) @@ -343,6 +345,65 @@ describe('Tests using .busted tasks', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) + assert.is_nil(args.f) + assert.is_nil(args['config-file']) + assert.is_nil(args.shuffle) + assert.is_nil(args['shuffle-files']) + assert.is_nil(args['shuffle-tests']) + assert.is_nil(args.sort) + assert.is_nil(args['sort-files']) + assert.is_nil(args['sort-tests']) + assert.is_nil(args.r) + assert.is_nil(args.run) + assert.is_nil(args.helper) + assert.is_same({'tag11', 'tag22', 'tag33'}, args.t) + assert.is_same({'tag11', 'tag22', 'tag33'}, args.tags) + assert.is_same({'etag11', 'etag22', 'etag33'}, args['exclude-tags']) + assert.is_same({}, args.filter) + assert.is_same({}, args['filter-out']) + assert.is_same({'-f', '--flag'}, args.Xoutput) + assert.is_same({'-v', '--verbose'}, args.Xhelper) + assert.is_same({'terra', 'moonscript'}, args.loaders) + end) + + it('default options with --config-file option', function() + local defaultOutput = 'default_output_handler' + local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' + local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' + local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local args = cli:parse({ '--config-file', 'spec/.hidden/.busted' }) + assert.is_equal(defaultOutput, args.o) + assert.is_equal(defaultOutput, args.output) + assert.is_same({'specs'}, args.ROOT) + assert.is_equal('./', args.C) + assert.is_equal('./', args.directory) + assert.is_equal('spec/.hidden/.busted', args.f) + assert.is_equal('spec/.hidden/.busted', args['config-file']) + assert.is_equal('_spec', args.p) + assert.is_equal('_spec%.lua$', args.pattern) + assert.is_equal('os.time()', args.seed) + assert.is_equal('en', args.lang) + assert.is_equal(1, args['repeat']) + assert.is_equal(lpath, args.m) + assert.is_equal(lpath, args.lpath) + assert.is_equal(cpath, args.cpath) + assert.is_true(args['auto-insulate']) + assert.is_true(args.k) + assert.is_true(args['keep-going']) + assert.is_true(args.R) + assert.is_true(args['recursive']) + assert.is_false(args.c) + assert.is_false(args.coverage) + assert.is_false(args.version) + assert.is_false(args.v) + assert.is_false(args.verbose) + assert.is_false(args.l) + assert.is_false(args.list) + assert.is_false(args.lazy) + assert.is_false(args.s) + assert.is_false(args['enable-sound']) + assert.is_false(args['suppress-pending']) + assert.is_false(args['defer-print']) assert.is_nil(args.shuffle) assert.is_nil(args['shuffle-files']) assert.is_nil(args['shuffle-tests']) From 39f73ae468049365239888ff2a07147b49b03fa1 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 20 Mar 2015 15:04:44 -0700 Subject: [PATCH 201/293] Remove unused variable --- busted/runner.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/runner.lua b/busted/runner.lua index 6bb50e12..3cdb2451 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -164,7 +164,7 @@ return function(options) local rootFiles = cliArgs.ROOT or { fileName } local pattern = cliArgs.pattern local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) - local fileList = testFileLoader(rootFiles, pattern, testFileLoaderOptions) + testFileLoader(rootFiles, pattern, testFileLoaderOptions) -- If running standalone, setup test file to be compatible with live coding if not cliArgs.ROOT then From c3ee7ba4ce177be98192e45f6a714992901b4a90 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 20 Mar 2015 15:07:08 -0700 Subject: [PATCH 202/293] Add a gtest style output handler This outputs the test name before a test is run and outputs any failures/errors as they are encountered. The `--defer-print` option can be used to defer the output of failures/errors to the end of the test suite. --- busted-2.0.rc7-0.rockspec | 1 + busted-scm-0.rockspec | 1 + busted/execute.lua | 2 +- busted/init.lua | 4 +- busted/outputHandlers/gtest.lua | 289 ++++++++++++++++++++++++++++++++ 5 files changed, 294 insertions(+), 3 deletions(-) create mode 100644 busted/outputHandlers/gtest.lua diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index fc7cbf6c..8e67d896 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -62,6 +62,7 @@ build = { ['busted.outputHandlers.TAP'] = 'busted/outputHandlers/TAP.lua', ['busted.outputHandlers.json'] = 'busted/outputHandlers/json.lua', ['busted.outputHandlers.junit'] = 'busted/outputHandlers/junit.lua', + ['busted.outputHandlers.gtest'] = 'busted/outputHandlers/gtest.lua', ['busted.outputHandlers.sound'] = 'busted/outputHandlers/sound.lua', ['busted.languages.en'] = 'busted/languages/en.lua', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 846dfef7..10fc7d51 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -61,6 +61,7 @@ build = { ['busted.outputHandlers.TAP'] = 'busted/outputHandlers/TAP.lua', ['busted.outputHandlers.json'] = 'busted/outputHandlers/json.lua', ['busted.outputHandlers.junit'] = 'busted/outputHandlers/junit.lua', + ['busted.outputHandlers.gtest'] = 'busted/outputHandlers/gtest.lua', ['busted.outputHandlers.sound'] = 'busted/outputHandlers/sound.lua', ['busted.languages.en'] = 'busted/languages/en.lua', diff --git a/busted/execute.lua b/busted/execute.lua index 3fbb3384..ae760940 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -31,7 +31,7 @@ return function(busted) end local root = busted.context.get() - busted.publish({ 'suite', 'start' }, i, runs) + busted.publish({ 'suite', 'start' }, i, runs, busted.randomize and busted.randomseed or nil) if block.setup(root) then busted.execute() end diff --git a/busted/init.lua b/busted/init.lua index 285b4dd2..f7bc5981 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -3,9 +3,9 @@ local function init(busted) local file = function(file) busted.wrap(file.run) - busted.publish({ 'file', 'start' }, file.name) + busted.publish({ 'file', 'start' }, file) block.execute('file', file) - busted.publish({ 'file', 'end' }, file.name) + busted.publish({ 'file', 'end' }, file) end local describe = function(describe) diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua new file mode 100644 index 00000000..a5fa7f0d --- /dev/null +++ b/busted/outputHandlers/gtest.lua @@ -0,0 +1,289 @@ +local s = require 'say' +local socket = require 'socket' +local pretty = require 'pl.pretty' +local term = require 'term' + +local colors + +local isatty = term.isatty(io.stdout) +local isWindows = package.config:sub(1,1) == '\\' + +if isWindows and not os.getenv("ANSICON") or not isatty then + colors = setmetatable({}, {__index = function() return function(s) return s end end}) +else + colors = require 'term.colors' +end + +return function(options, busted) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() + + local repeatSuiteString = '\nRepeating all tests (run %d of %d) . . .\n\n' + local randomizeString = 'Note: Randomizing test order with a seed of %d.\n' + local suiteStartString = colors.green ('[==========]') .. ' Running tests from scanned files.\n' + local globalSetup = colors.green ('[----------]') .. ' Global test environment setup.\n' + local fileStartString = colors.green ('[----------]') .. ' Running tests from %s\n' + local runString = colors.green ('[ RUN ]') .. ' %s\n' + local successString = colors.green ('[ OK ]') .. ' %s (%.2f ms)\n' + local skippedString = colors.yellow ('[ SKIPPED ]') .. ' %s (%.2f ms)\n' + local failureString = colors.red ('[ FAILED ]') .. ' %s (%.2f ms)\n' + local errorString = colors.magenta('[ ERROR ]') .. ' %s (%.2f ms)\n' + local fileEndString = colors.green ('[----------]') .. ' %d %s from %s (%.2f ms total)\n\n' + local globalTeardown = colors.green ('[----------]') .. ' Global test environment teardown.\n' + local suiteEndString = colors.green ('[==========]') .. ' %d %s from %d test %s ran. (%.2f ms total)\n' + local successStatus = colors.green ('[ PASSED ]') .. ' %d %s.\n' + + local summaryStrings = { + skipped = { + header = colors.yellow ('[ SKIPPED ]') .. ' %d %s, listed below:\n', + test = colors.yellow ('[ SKIPPED ]') .. ' %s\n', + footer = ' %d SKIPPED %s\n', + }, + + failure = { + header = colors.red ('[ FAILED ]') .. ' %d %s, listed below:\n', + test = colors.red ('[ FAILED ]') .. ' %s\n', + footer = ' %d FAILED %s\n', + }, + + error = { + header = colors.magenta('[ ERROR ]') .. ' %d %s, listed below:\n', + test = colors.magenta('[ ERROR ]') .. ' %s\n', + footer = ' %d %s\n', + }, + } + + local fileCount = 0 + local testCount = 0 + local successCount = 0 + local skippedCount = 0 + local failureCount = 0 + local errorCount = 0 + + local suiteStartTime + local fileStartTime + local testStartTime + + local pendingDescription = function(pending) + local name = pending.name + local string = '' + + if type(pending.message) == 'string' then + string = string .. pending.message .. '\n' + elseif pending.message ~= nil then + string = string .. pretty.write(pending.message) .. '\n' + end + + return string + end + + local failureDescription = function(failure) + local string + if type(failure.message) == 'string' then + string = failure.message + elseif failure.message == nil then + string = 'Nil error' + else + string = pretty.write(failure.message) + end + + string = string .. '\n' + + if options.verbose and failure.trace and failure.trace.traceback then + string = string .. failure.trace.traceback .. '\n' + end + + return string + end + + local getFileLine = function(element) + local fileline = '' + if element.trace or element.trace.short_src then + fileline = colors.cyan(element.trace.short_src) .. ' @ ' .. + colors.cyan(element.trace.currentline) .. ': ' + end + return fileline + end + + local getTestList = function(status, count, list, getDescription) + local string = '' + local header = summaryStrings[status].header + if count > 0 and header then + local tests = (count == 1 and 'test' or 'tests') + local errors = (count == 1 and 'error' or 'errors') + string = header:format(count, status == 'error' and errors or tests) + + local testString = summaryStrings[status].test + if testString then + for _, t in ipairs(list) do + local fullname = getFileLine(t.element) .. colors.bright(t.name) + string = string .. testString:format(fullname) + if options.deferPrint then + string = string .. getDescription(t) + end + end + end + end + return string + end + + local getSummary = function(status, count) + local string = '' + local footer = summaryStrings[status].footer + if count > 0 and footer then + local tests = (count == 1 and 'TEST' or 'TESTS') + local errors = (count == 1 and 'ERROR' or 'ERRORS') + string = footer:format(count, status == 'error' and errors or tests) + end + return string + end + + local getSummaryString = function() + local tests = (successCount == 1 and 'test' or 'tests') + local string = successStatus:format(successCount, tests) + + string = string .. getTestList('skipped', skippedCount, handler.pendings, pendingDescription) + string = string .. getTestList('failure', failureCount, handler.failures, failureDescription) + string = string .. getTestList('error', errorCount, handler.errors, failureDescription) + + string = string .. ((skippedCount + failureCount + errorCount) > 0 and '\n' or '') + string = string .. getSummary('skipped', skippedCount) + string = string .. getSummary('failure', failureCount) + string = string .. getSummary('error', errorCount) + + return string + end + + local getFullName = function(element) + return getFileLine(element) .. colors.bright(handler.getFullName(element)) + end + + handler.suiteReset = function() + fileCount = 0 + testCount = 0 + successCount = 0 + skippedCount = 0 + failureCount = 0 + errorCount = 0 + + return nil, true + end + + handler.suiteStart = function(count, total, randomseed) + suiteStartTime = socket.gettime() + if total > 1 then + io.write(repeatSuiteString:format(count, total)) + end + if randomseed then + io.write(randomizeString:format(randomseed)) + end + io.write(suiteStartString) + io.write(globalSetup) + io.flush() + + return nil, true + end + + handler.suiteEnd = function(count, total) + local elapsedTime_ms = (socket.gettime() - suiteStartTime) * 1000 + local tests = (testCount == 1 and 'test' or 'tests') + local files = (fileCount == 1 and 'file' or 'files') + io.write(globalTeardown) + io.write(suiteEndString:format(testCount, tests, fileCount, files, elapsedTime_ms)) + io.write(getSummaryString()) + io.flush() + + return nil, true + end + + handler.fileStart = function(file) + fileStartTime = socket.gettime() + io.write(fileStartString:format(file.name)) + io.flush() + return nil, true + end + + handler.fileEnd = function(file) + local elapsedTime_ms = (socket.gettime() - fileStartTime) * 1000 + local tests = (testCount == 1 and 'test' or 'tests') + fileCount = fileCount + 1 + io.write(fileEndString:format(testCount, tests, file.name, elapsedTime_ms)) + io.flush() + return nil, true + end + + handler.testStart = function(element, parent) + testStartTime = socket.gettime() + io.write(runString:format(getFullName(element))) + io.flush() + + return nil, true + end + + handler.testEnd = function(element, parent, status, debug) + local elapsedTime_ms = (socket.gettime() - testStartTime) * 1000 + local string + + testCount = testCount + 1 + if status == 'success' then + successCount = successCount + 1 + string = successString + elseif status == 'pending' then + skippedCount = skippedCount + 1 + string = skippedString + elseif status == 'failure' then + failureCount = failureCount + 1 + string = failureString + elseif status == 'error' then + errorCount = errorCount + 1 + string = errorString + end + + io.write(string:format(getFullName(element), elapsedTime_ms)) + io.flush() + + return nil, true + end + + handler.testFailure = function(element, parent, message, debug) + if not options.deferPrint then + io.write(failureDescription(handler.failures[#handler.failures])) + io.flush() + end + return nil, true + end + + handler.testError = function(element, parent, message, debug) + if not options.deferPrint then + io.write(failureDescription(handler.errors[#handler.errors])) + io.flush() + end + return nil, true + end + + handler.error = function(element, parent, message, debug) + if element.descriptor ~= 'it' then + if not options.deferPrint then + io.write(failureDescription(handler.errors[#handler.errors])) + io.flush() + end + errorCount = errorCount + 1 + end + + return nil, true + end + + busted.subscribe({ 'suite', 'reset' }, handler.suiteReset) + busted.subscribe({ 'suite', 'start' }, handler.suiteStart) + busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) + busted.subscribe({ 'file', 'start' }, handler.fileStart) + busted.subscribe({ 'file', 'end' }, handler.fileEnd) + busted.subscribe({ 'test', 'start' }, handler.testStart, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'failure', 'it' }, handler.testFailure) + busted.subscribe({ 'error', 'it' }, handler.testError) + busted.subscribe({ 'failure' }, handler.error) + busted.subscribe({ 'error' }, handler.error) + + return handler +end From 2433f681de6c0e7cf30d413d5e535b07f1463430 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 6 Apr 2015 13:44:10 -0700 Subject: [PATCH 203/293] Upgrade penlight version This updates the version of penlight used by busted to the version of penlight that fixes `path.normpath`. With the updated version of penlight, busted no longer needs its own version of `normpath`, it can just use `path.normpath` directly from the penlight module. --- busted-2.0.rc7-0.rockspec | 2 +- busted-scm-0.rockspec | 2 +- busted/modules/cli.lua | 2 +- busted/modules/helper_loader.lua | 6 ++-- busted/modules/output_handler_loader.lua | 6 ++-- busted/runner.lua | 2 +- busted/utils.lua | 35 ------------------------ spec/cl_spec.lua | 2 +- 8 files changed, 11 insertions(+), 46 deletions(-) diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index 8e67d896..32a70f37 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -26,7 +26,7 @@ dependencies = { 'luassert >= 1.7.4-0', 'ansicolors >= 1.0-1', 'lua-term >= 0.1-1', - 'penlight >= 1.0.0-1', + 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1-3', } build = { diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 10fc7d51..1892b0e6 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -25,7 +25,7 @@ dependencies = { 'say >= 1.3-0', 'luassert >= 1.7.4-0', 'lua-term >= 0.1-1', - 'penlight >= 1.0.0-1', + 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1-3', } build = { diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 11807ac6..8008841d 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -159,7 +159,7 @@ return function(options) -- Load busted config file if available local configFile = { } - local bustedConfigFilePath = cliArgs.f or utils.normpath(path.join(cliArgs.directory, '.busted')) + local bustedConfigFilePath = cliArgs.f or path.normpath(path.join(cliArgs.directory, '.busted')) local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) if bustedConfigFile then local config, err = configLoader(configFile, cliArgsParsed, cliArgs) diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index 17cde472..693b903d 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -1,4 +1,4 @@ -local utils = require 'busted.utils' +local path = require 'pl.path' local hasMoon, moonscript = pcall(require, 'moonscript') return function() @@ -7,9 +7,9 @@ return function() local success, err = pcall(function() arg = options.arguments if helper:match('%.lua$') then - dofile(utils.normpath(helper)) + dofile(path.normpath(helper)) elseif hasMoon and helper:match('%.moon$') then - moonscript.dofile(utils.normpath(helper)) + moonscript.dofile(path.normpath(helper)) else require(helper) end diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index c507c460..14ab9299 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -1,4 +1,4 @@ -local utils = require 'busted.utils' +local path = require 'pl.path' local hasMoon, moonscript = pcall(require, 'moonscript') return function() @@ -7,9 +7,9 @@ return function() local success, err = pcall(function() if output:match('%.lua$') then - handler = dofile(utils.normpath(output)) + handler = dofile(path.normpath(output)) elseif hasMoon and output:match('%.moon$') then - handler = moonscript.dofile(utils.normpath(output)) + handler = moonscript.dofile(path.normpath(output)) else handler = require('busted.outputHandlers.' .. output) end diff --git a/busted/runner.lua b/busted/runner.lua index 3cdb2451..5cddcd1b 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -44,7 +44,7 @@ return function(options) end -- Load current working directory - local _, err = path.chdir(utils.normpath(cliArgs.directory)) + local _, err = path.chdir(path.normpath(cliArgs.directory)) if err then io.stderr:write(appName .. ': error: ' .. err .. '\n') osexit(1, true) diff --git a/busted/utils.lua b/busted/utils.lua index 4e02bc03..a8d359c4 100644 --- a/busted/utils.lua +++ b/busted/utils.lua @@ -2,44 +2,9 @@ local path = require 'pl.path' math.randomseed(os.time()) --- Do not use pl.path.normpath --- It is broken for paths with leading '../../' -local function normpath(fpath) - if type(fpath) ~= 'string' then - error(fpath .. ' is not a string') - end - local sep = '/' - if path.is_windows then - sep = '\\' - if fpath:match '^\\\\' then -- UNC - return '\\\\' .. normpath(fpath:sub(3)) - end - fpath = fpath:gsub('/','\\') - end - local np_gen1, np_gen2 = '([^SEP]+)SEP(%.%.SEP?)', 'SEP+%.?SEP' - local np_pat1 = np_gen1:gsub('SEP', sep) - local np_pat2 = np_gen2:gsub('SEP', sep) - local k - repeat -- /./ -> / - fpath, k = fpath:gsub(np_pat2, sep) - until k == 0 - repeat -- A/../ -> (empty) - local oldpath = fpath - fpath, k = fpath:gsub(np_pat1, function(d, up) - if d == '..' then return nil end - if d == '.' then return up end - return '' - end) - until k == 0 or oldpath == fpath - if fpath == '' then fpath = '.' end - return fpath -end - return { split = require 'pl.utils'.split, - normpath = normpath, - shuffle = function(t, seed) if seed then math.randomseed(seed) end local n = #t diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index cec45e9d..c1073210 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -1,6 +1,6 @@ local utils = require 'pl.utils' local path = require 'pl.path' -local normpath = require 'busted.utils'.normpath +local normpath = path.normpath local busted_cmd = path.is_windows and 'lua bin/busted' or 'bin/busted' local ditch = path.is_windows and ' 1> NUL 2>NUL' or ' > /dev/null 2>&1' From 8df348800734939662733f791d601d97fa48aabd Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 6 Apr 2015 15:12:03 -0700 Subject: [PATCH 204/293] Update version of Lua/LuaJIT used by travis builds This updates the travis builds to use the latest versions of Lua, LuaJIT, and LuaRocks. --- .travis.yml | 1 + .travis_setup.sh | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index f53b5bba..1914788c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: c env: - LUA='Lua 5.1' - LUA='Lua 5.2' + - LUA='Lua 5.3' - LUA='LuaJIT 2.0' before_install: diff --git a/.travis_setup.sh b/.travis_setup.sh index 4982fdbf..09b662ba 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -1,6 +1,6 @@ -# A script for setting up environment for travis-ci testing. -# Sets up Lua and Luarocks. -# LUA must be "Lua 5.1", "Lua 5.2" or "LuaJIT 2.0". +# A script for setting up environment for travis-ci testing. +# Sets up Lua and Luarocks. +# LUA must be "Lua 5.1", "Lua 5.2", "Lua 5.3" or "LuaJIT 2.0". set -e @@ -11,23 +11,26 @@ echo 'rocks_servers = { if [ "$LUA" == "LuaJIT 2.0" ]; then - wget -O - http://luajit.org/download/LuaJIT-2.0.2.tar.gz | tar xz - cd LuaJIT-2.0.2 + wget -O - http://luajit.org/download/LuaJIT-2.0.3.tar.gz | tar xz + cd LuaJIT-2.0.3 make && sudo make install INSTALL_TSYMNAME=lua; else if [ "$LUA" == "Lua 5.1" ]; then wget -O - http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz cd lua-5.1.5; elif [ "$LUA" == "Lua 5.2" ]; then - wget -O - http://www.lua.org/ftp/lua-5.2.3.tar.gz | tar xz - cd lua-5.2.3; + wget -O - http://www.lua.org/ftp/lua-5.2.4.tar.gz | tar xz + cd lua-5.2.4; + elif [ "$LUA" == "Lua 5.3" ]; then + wget -O - http://www.lua.org/ftp/lua-5.3.0.tar.gz | tar xz + cd lua-5.3.0; fi sudo make linux install; fi cd .. -wget -O - http://luarocks.org/releases/luarocks-2.2.0.tar.gz | tar xz -cd luarocks-2.2.0 +wget -O - http://luarocks.org/releases/luarocks-2.2.1.tar.gz | tar xz +cd luarocks-2.2.1 if [ "$LUA" == "LuaJIT 2.0" ]; then ./configure --with-lua-include=/usr/local/include/luajit-2.0; From d08d3d8d3b628842e310f28b6d4fffe63660591a Mon Sep 17 00:00:00 2001 From: Kyle McLamb Date: Tue, 7 Apr 2015 04:49:52 -0400 Subject: [PATCH 205/293] Add missing luasocket dependency --- busted-2.0.rc7-0.rockspec | 1 + busted-scm-0.rockspec | 1 + 2 files changed, 2 insertions(+) diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc7-0.rockspec index 8e67d896..aadc0522 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc7-0.rockspec @@ -28,6 +28,7 @@ dependencies = { 'lua-term >= 0.1-1', 'penlight >= 1.0.0-1', 'mediator_lua >= 1.1-3', + 'luasocket >= 2.0.1' } build = { type = 'builtin', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 10fc7d51..13d1a7f8 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -27,6 +27,7 @@ dependencies = { 'lua-term >= 0.1-1', 'penlight >= 1.0.0-1', 'mediator_lua >= 1.1-3', + 'luasocket >= 2.0.1' } build = { type = 'builtin', From 9e8892fb36242c4f92df003b4bf2e6884a73c7e3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 11 Apr 2015 23:12:50 -0700 Subject: [PATCH 206/293] Replace norandomize() with randomize(false) This removes the `norandomize` function and overloads the `randomize` function to take an argument to enable/disable randomization. Calling `randomize` with no arguments enables randomization by default. --- busted/block.lua | 6 +++--- spec/core_spec.lua | 4 +--- spec/randomize_spec.lua | 24 ++++++++++++++++++++++-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/busted/block.lua b/busted/block.lua index c51b5f42..52e789a5 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -26,7 +26,6 @@ return function(busted) function block.rejectAll(element) block.reject('randomize', element) - block.reject('norandomize', element) for descriptor, _ in pairs(busted.executors) do block.reject(descriptor, element) end @@ -135,8 +134,9 @@ return function(busted) if not element.env then element.env = {} end local randomize = busted.randomize - element.env.randomize = function() randomize = true end - element.env.norandomize = function() randomize = false end + element.env.randomize = function(...) + randomize = (select('#', ...) == 0 or ...) + end if busted.safe(descriptor, element.run, element):success() then if randomize then diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 08a542c7..9d61bbbf 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -368,9 +368,8 @@ describe('tests unsupported functions', function() assert.has_error(strict_teardown, "'strict_teardown' not supported inside current context block") end) - it('it block throws error on randomize/norandomize', function() + it('it block throws error on randomize', function() assert.has_error(randomize, "'randomize' not supported inside current context block") - assert.has_error(norandomize, "'norandomize' not supported inside current context block") end) it('finaly block throws error on pending', function() @@ -385,7 +384,6 @@ describe('tests unsupported functions in setup/before_each/after_each/teardown', assert.is_nil(file) assert.is_nil(finally) assert.has_error(randomize, "'randomize' not supported inside current context block") - assert.has_error(norandomize, "'norandomize' not supported inside current context block") assert.has_error(describe, "'describe' not supported inside current context block") assert.has_error(context, "'context' not supported inside current context block") diff --git a/spec/randomize_spec.lua b/spec/randomize_spec.lua index 2fa6e014..2b78d22c 100644 --- a/spec/randomize_spec.lua +++ b/spec/randomize_spec.lua @@ -19,9 +19,29 @@ describe('Order of tests ran', function() end) end) -describe('Disabling randomized test order', function() +describe('Disabling randomized test order with randomize(false)', function() randomize() - norandomize() + randomize(false) + + local expected = {} + local order = {} + + for i = 1, 100 do + table.insert(expected, i) + + it('does 100 its', function() + table.insert(order, i) + end) + end + + it('does not randomize tests', function() + assert.are.same(expected, order) + end) +end) + +describe('Disabling randomized test order with randomize(nil)', function() + randomize() + randomize(nil) local expected = {} local order = {} From fae70cfd4734ab270a41b95e8006fafec24056df Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 13 Apr 2015 12:51:18 -0700 Subject: [PATCH 207/293] Only run moonscript tests if moonscript is present This updates the moonscript specs to detect whether or not moonscript is present, and if not marks all moonscript tests as pending, instead of attempting to execute them. --- spec/cl_spec.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index c1073210..c693421c 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -562,7 +562,10 @@ describe('Tests error messages through the command line', function() end) end) -describe('Tests moonscript error messages through the command line', function() +local has_moon = pcall(require, 'moonscript') +local describe_moon = (has_moon and describe or pending) + +describe_moon('Tests moonscript error messages through the command line', function() it('when assertion fails', function() error_start() local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') From feb5adbe2eb2979bdc65557fe0e3817b19849417 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 13 Apr 2015 19:08:27 -0700 Subject: [PATCH 208/293] Update rockspec to use https url for cloning --- busted-scm-0.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 68cb8c81..39e4420e 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -1,7 +1,7 @@ package = 'busted' version = 'scm-0' source = { - url = "git://github.com/Olivine-Labs/busted", + url = "https://github.com/Olivine-Labs/busted.git", branch = "master" } description = { From aab5d19d0c615a33b865ebc771fdef80edb99356 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 14 Apr 2015 09:07:01 -0700 Subject: [PATCH 209/293] Use git protocol in scm rockspec This undos the previous change to use https protocol for git since luarocks does not support https using git. --- busted-scm-0.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 39e4420e..68cb8c81 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -1,7 +1,7 @@ package = 'busted' version = 'scm-0' source = { - url = "https://github.com/Olivine-Labs/busted.git", + url = "git://github.com/Olivine-Labs/busted", branch = "master" } description = { From 366b39ca56dcabd28897985b6bc4bcb42e193740 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Wed, 15 Apr 2015 12:02:52 -0700 Subject: [PATCH 210/293] v2.0.rc8 --- busted-2.0.rc7-0.rockspec => busted-2.0.rc8-0.rockspec | 10 +++++----- busted-scm-0.rockspec | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) rename busted-2.0.rc7-0.rockspec => busted-2.0.rc8-0.rockspec (95%) diff --git a/busted-2.0.rc7-0.rockspec b/busted-2.0.rc8-0.rockspec similarity index 95% rename from busted-2.0.rc7-0.rockspec rename to busted-2.0.rc8-0.rockspec index ec2ee60b..ba78e2e9 100644 --- a/busted-2.0.rc7-0.rockspec +++ b/busted-2.0.rc8-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc7-0' +version = '2.0.rc8-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc7-0.tar.gz', - dir = 'busted-2.0.rc7-0' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc8-0.tar.gz', + dir = 'busted-2.0.rc8-0' } description = { summary = 'Elegant Lua unit testing.', @@ -23,11 +23,11 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', - 'luassert >= 1.7.4-0', + 'luassert >= 1.7.6-0', 'ansicolors >= 1.0-1', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', - 'mediator_lua >= 1.1-3', + 'mediator_lua >= 1.1.1-0', 'luasocket >= 2.0.1' } build = { diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 68cb8c81..97fd8df1 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -23,10 +23,10 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', - 'luassert >= 1.7.4-0', + 'luassert >= 1.7.6-0', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', - 'mediator_lua >= 1.1-3', + 'mediator_lua >= 1.1.1-0', 'luasocket >= 2.0.1' } build = { From d8218f085941f888004e44f4e954783cf1759447 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 8 May 2015 00:17:28 -0700 Subject: [PATCH 211/293] Fix getmetatable calls Use `debug.getmetatable` instead of `getmetatable` in case there is a `__metatable` field present in the object's metatable. --- busted/context.lua | 2 +- busted/core.lua | 10 +++++----- busted/runner.lua | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/busted/context.lua b/busted/context.lua index c2e28921..a1ad2472 100644 --- a/busted/context.lua +++ b/busted/context.lua @@ -6,7 +6,7 @@ local function save() g[k] = rawget(_G, k) end return { - gmt = getmetatable(_G), + gmt = debug.getmetatable(_G), g = g, loaded = tablex.copy(package.loaded) } diff --git a/busted/core.lua b/busted/core.lua index c36ba652..56bdd6ba 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -24,15 +24,15 @@ local pendingMt = { local function metatype(obj) local otype = type(obj) - return otype == 'table' and (getmetatable(obj) or {}).__type or otype + return otype == 'table' and (debug.getmetatable(obj) or {}).__type or otype end local function hasToString(obj) - return type(obj) == 'string' or (getmetatable(obj) or {}).__tostring + return type(obj) == 'string' or (debug.getmetatable(obj) or {}).__tostring end local function isCallable(obj) - return (type(obj) == 'function' or (getmetatable(obj) or {}).__call) + return type(obj) == 'function' or (debug.getmetatable(obj) or {}).__call end return function() @@ -143,7 +143,7 @@ return function() function busted.bindfenv(callable, var, value) local env = {} - local f = (getmetatable(callable) or {}).__call or callable + local f = (debug.getmetatable(callable) or {}).__call or callable setmetatable(env, { __index = getfenv(f) }) env[var] = value setfenv(f, env) @@ -152,7 +152,7 @@ return function() function busted.wrap(callable) if isCallable(callable) then -- prioritize __call if it exists, like in files - environment.wrap((getmetatable(callable) or {}).__call or callable) + environment.wrap((debug.getmetatable(callable) or {}).__call or callable) end end diff --git a/busted/runner.lua b/busted/runner.lua index 5cddcd1b..f41923f6 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -171,7 +171,7 @@ return function(options) local ctx = busted.context.get() local children = busted.context.children(ctx) local file = children[#children] - getmetatable(file.run).__call = info.func + debug.getmetatable(file.run).__call = info.func end local runs = cliArgs['repeat'] From 93453c3f2e33820a7e9eb3e7d61360fd27052cda Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Fri, 8 May 2015 16:21:36 -0400 Subject: [PATCH 212/293] Fix incorrect busted.version Closes #413 --- busted/core.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/core.lua b/busted/core.lua index 56bdd6ba..5d304d46 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -39,7 +39,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc6-0' + busted.version = '2.0.rc8-0' local root = require 'busted.context'() busted.context = root.ref() From 762617be3d1bd3544547871e362611178cf75434 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 8 May 2015 00:46:05 -0700 Subject: [PATCH 213/293] Fix specs to match latest luassert changes This updates specs to pass against the latest changes made to luassert. --- busted-2.0.rc8-0.rockspec | 2 +- busted-scm-0.rockspec | 2 +- spec/core_spec.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/busted-2.0.rc8-0.rockspec b/busted-2.0.rc8-0.rockspec index ba78e2e9..dda7dfbd 100644 --- a/busted-2.0.rc8-0.rockspec +++ b/busted-2.0.rc8-0.rockspec @@ -23,7 +23,7 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', - 'luassert >= 1.7.6-0', + 'luassert >= 1.7.7-0', 'ansicolors >= 1.0-1', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 97fd8df1..79377faa 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -23,7 +23,7 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', - 'luassert >= 1.7.6-0', + 'luassert >= 1.7.7-0', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1.1-0', diff --git a/spec/core_spec.lua b/spec/core_spec.lua index 9d61bbbf..ba0c07a5 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -9,7 +9,7 @@ assert(type(before_each) == 'function') assert(type(after_each) == 'function') assert(type(spy) == 'table') assert(type(stub) == 'table') -assert(type(mock) == 'function') +assert(type(mock) == 'table') assert(type(assert) == 'table') describe('Before each', function() From b410a0a05df74cdb4ec2eba381fde31fa1ae0931 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 28 May 2015 01:26:21 -0700 Subject: [PATCH 214/293] Remove unnecessary arg to gtest output handler --- busted/outputHandlers/gtest.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index a5fa7f0d..e136a216 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -14,7 +14,7 @@ else colors = require 'term.colors' end -return function(options, busted) +return function(options) local busted = require 'busted' local handler = require 'busted.outputHandlers.base'() From f9bfa978557176c4064b4dba44e70718de699ea4 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 30 May 2015 00:10:08 -0700 Subject: [PATCH 215/293] Add luarocks backup server Add a backup server from which to download luarocks. --- .travis_setup.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis_setup.sh b/.travis_setup.sh index 09b662ba..f866f47b 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -6,7 +6,9 @@ set -e echo 'rocks_servers = { "http://rocks.moonscript.org/", - "http://luarocks.org/repositories/rocks" + "http://luarocks.org/repositories/rocks", + "http://luarocks.logiceditor.com/rocks", + "http://liblua.so/luarocks/repositories/rocks" }' >> ~/config.lua @@ -29,7 +31,7 @@ else fi cd .. -wget -O - http://luarocks.org/releases/luarocks-2.2.1.tar.gz | tar xz +wget -O - http://luarocks.org/releases/luarocks-2.2.1.tar.gz | tar xz || wget -O - http://keplerproject.github.io/luarocks/releases/luarocks-2.2.1.tar.gz | tar xz cd luarocks-2.2.1 if [ "$LUA" == "LuaJIT 2.0" ]; then From f59a9354eb1cd40566fc5500f9ec24d42343c545 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 30 May 2015 00:11:29 -0700 Subject: [PATCH 216/293] Update luarocks to version 2.2.2 --- .travis_setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis_setup.sh b/.travis_setup.sh index f866f47b..00ddeee0 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -31,8 +31,8 @@ else fi cd .. -wget -O - http://luarocks.org/releases/luarocks-2.2.1.tar.gz | tar xz || wget -O - http://keplerproject.github.io/luarocks/releases/luarocks-2.2.1.tar.gz | tar xz -cd luarocks-2.2.1 +wget -O - http://luarocks.org/releases/luarocks-2.2.2.tar.gz | tar xz || wget -O - http://keplerproject.github.io/luarocks/releases/luarocks-2.2.2.tar.gz | tar xz +cd luarocks-2.2.2 if [ "$LUA" == "LuaJIT 2.0" ]; then ./configure --with-lua-include=/usr/local/include/luajit-2.0; From 772d1ae9bf5467915b15bbf7bd3e08ae68ce9a3d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 30 May 2015 00:42:09 -0700 Subject: [PATCH 217/293] Install released version of lua-ev --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1914788c..5b2caa54 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ install: - sudo apt-get update -qq - sudo luarocks install luasec - sudo apt-get install -qq libev-dev - - sudo luarocks install lua-ev scm --server=http://luarocks.org/repositories/rocks-scm/ + - sudo luarocks install lua-ev - sudo luarocks install copas - sudo luarocks install moonscript - sudo luarocks make busted-scm-0.rockspec From e8d51ac06795b321656334a80a018cf01c0f7704 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 30 May 2015 00:59:05 -0700 Subject: [PATCH 218/293] Do not install lib-ev or copas Since async tests are not currently supported, lib-ev and copas do not need to be installed. --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b2caa54..bf143ba7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,6 @@ before_install: install: - sudo apt-get update -qq - sudo luarocks install luasec - - sudo apt-get install -qq libev-dev - - sudo luarocks install lua-ev - - sudo luarocks install copas - sudo luarocks install moonscript - sudo luarocks make busted-scm-0.rockspec From 841520fdc66036dbafc947925c3bb8a4d25752fa Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 29 May 2015 21:44:22 -0700 Subject: [PATCH 219/293] Refactor error type detection --- busted/core.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index 5d304d46..faa2dbfe 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -22,9 +22,14 @@ local pendingMt = { __type = 'pending' } -local function metatype(obj) - local otype = type(obj) - return otype == 'table' and (debug.getmetatable(obj) or {}).__type or otype +local function errortype(obj) + local mt = debug.getmetatable(obj) + if mt == failureMt or mt == failureMtNoString then + return 'failure' + elseif mt == pendingMt then + return 'pending' + end + return 'error' end local function hasToString(obj) @@ -162,8 +167,7 @@ return function() local status = 'success' local ret = { xpcall(run, function(msg) - local errType = metatype(msg) - status = ((errType == 'pending' or errType == 'failure') and errType or 'error') + status = errortype(msg) trace = busted.getTrace(element, 3, msg) message = busted.rewriteMessage(element, msg, trace) end) } From c9fe25c536b85738f34e84390279bb8f6cc7c818 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 29 May 2015 23:17:07 -0700 Subject: [PATCH 220/293] Wrap publish start/end messages in a safe call --- busted/context.lua | 6 ++--- busted/core.lua | 9 +++++++ busted/execute.lua | 14 +++++----- busted/init.lua | 36 +++++++++++++++---------- busted/outputHandlers/gtest.lua | 4 +-- busted/outputHandlers/junit.lua | 4 +-- busted/outputHandlers/plainTerminal.lua | 2 +- busted/outputHandlers/utfTerminal.lua | 4 +-- 8 files changed, 49 insertions(+), 30 deletions(-) diff --git a/busted/context.lua b/busted/context.lua index a1ad2472..2a8bc6b9 100644 --- a/busted/context.lua +++ b/busted/context.lua @@ -25,7 +25,7 @@ end return function() local context = {} - local data = {} + local data = { descriptor = 'suite', attributes = {} } local parents = {} local children = {} local stack = {} @@ -87,7 +87,7 @@ return function() end function ref.clear() - data = {} + data = { descriptor = 'suite', attributes = {} } parents = {} children = {} stack = {} @@ -110,7 +110,7 @@ return function() end function ref.push(current) - if not parents[current] then error('Detached child. Cannot push.') end + if not parents[current] and current ~= data then error('Detached child. Cannot push.') end if ctx ~= current then push_state(current) end table.insert(stack, ctx) ctx = current diff --git a/busted/core.lua b/busted/core.lua index 5d304d46..9537ebf9 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -177,6 +177,15 @@ return function() return unpack(ret) end + function busted.safe_publish(descriptor, channel, element, ...) + local args = {...} + local n = select('#', ...) + local status = busted.safe(descriptor, function() + busted.publish(channel, element, unpack(args, 1, n)) + end, element) + return status:success() + end + function busted.exportApi(key, value) busted.api[key] = value end diff --git a/busted/execute.lua b/busted/execute.lua index ae760940..7f90298c 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -31,13 +31,15 @@ return function(busted) end local root = busted.context.get() - busted.publish({ 'suite', 'start' }, i, runs, busted.randomize and busted.randomseed or nil) - if block.setup(root) then - busted.execute() + local seed = (busted.randomize and busted.randomseed or nil) + if busted.safe_publish('suite', { 'suite', 'start' }, root, i, runs, seed) then + if block.setup(root) then + busted.execute() + end + block.lazyTeardown(root) + block.teardown(root) end - block.lazyTeardown(root) - block.teardown(root) - busted.publish({ 'suite', 'end' }, i, runs) + busted.safe_publish('suite', { 'suite', 'end' }, root, i, runs) if busted.skipAll then break diff --git a/busted/init.lua b/busted/init.lua index f7bc5981..64cedfc1 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -3,16 +3,18 @@ local function init(busted) local file = function(file) busted.wrap(file.run) - busted.publish({ 'file', 'start' }, file) - block.execute('file', file) - busted.publish({ 'file', 'end' }, file) + if busted.safe_publish('file', { 'file', 'start' }, file) then + block.execute('file', file) + end + busted.safe_publish('file', { 'file', 'end' }, file) end local describe = function(describe) local parent = busted.context.parent(describe) - busted.publish({ 'describe', 'start' }, describe, parent) - block.execute('describe', describe) - busted.publish({ 'describe', 'end' }, describe, parent) + if busted.safe_publish('describe', { 'describe', 'start' }, describe, parent) then + block.execute('describe', describe) + end + busted.safe_publish('describe', { 'describe', 'end' }, describe, parent) end local it = function(element) @@ -34,13 +36,16 @@ local function init(busted) if pass then local status = busted.status('success') - busted.publish({ 'test', 'start' }, element, parent) - status:update(busted.safe('it', element.run, element)) - if finally then - block.reject('pending', element) - status:update(busted.safe('finally', finally, element)) + if busted.safe_publish('it', { 'test', 'start' }, element, parent) then + status:update(busted.safe('it', element.run, element)) + if finally then + block.reject('pending', element) + status:update(busted.safe('finally', finally, element)) + end + else + status = busted.status('error') end - busted.publish({ 'test', 'end' }, element, parent, tostring(status)) + busted.safe_publish('it', { 'test', 'end' }, element, parent, tostring(status)) end block.dexecAll('after_each', ancestor, true) @@ -48,8 +53,11 @@ local function init(busted) local pending = function(element) local parent = busted.context.parent(element) - busted.publish({ 'test', 'start' }, element, parent) - busted.publish({ 'test', 'end' }, element, parent, 'pending') + local status = 'pending' + if not busted.safe_publish('it', { 'test', 'start' }, element, parent) then + status = 'error' + end + busted.safe_publish('it', { 'test', 'end' }, element, parent, status) end busted.register('file', file, { envmode = 'insulate' }) diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index e136a216..b6167601 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -169,7 +169,7 @@ return function(options) return nil, true end - handler.suiteStart = function(count, total, randomseed) + handler.suiteStart = function(suite, count, total, randomseed) suiteStartTime = socket.gettime() if total > 1 then io.write(repeatSuiteString:format(count, total)) @@ -184,7 +184,7 @@ return function(options) return nil, true end - handler.suiteEnd = function(count, total) + handler.suiteEnd = function(suite, count, total) local elapsedTime_ms = (socket.gettime() - suiteStartTime) * 1000 local tests = (testCount == 1 and 'test' or 'tests') local files = (fileCount == 1 and 'file' or 'files') diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index ea851c9c..348c3112 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -18,7 +18,7 @@ return function(options) local testcase_node local testStartTime - handler.suiteStart = function(count, total) + handler.suiteStart = function(suite, count, total) local suite = { start_time = socket.gettime(), xml_doc = xml.new('testsuite', { @@ -41,7 +41,7 @@ return function(options) return string.format("%.2f", (socket.gettime() - start_time)) end - handler.suiteEnd = function(count, total) + handler.suiteEnd = function(suite, count, total) local suite = top suite.xml_doc.attr.time = elapsed(suite.start_time) diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index ac6a4226..99276578 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -129,7 +129,7 @@ return function(options) return nil, true end - handler.suiteStart = function(count, total) + handler.suiteStart = function(suite, count, total) local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') io.write(runString:format(count, total)) io.flush() diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index d04b51a5..b6470d14 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -138,7 +138,7 @@ return function(options) return nil, true end - handler.suiteStart = function(count, total) + handler.suiteStart = function(suite, count, total) local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') io.write(runString:format(count, total)) io.flush() @@ -146,7 +146,7 @@ return function(options) return nil, true end - handler.suiteEnd = function(count, total) + handler.suiteEnd = function(suite, count, total) print('') print(statusString()) From f930f815e03a92916237500d65572502797c8939 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Sat, 30 May 2015 08:52:09 -0700 Subject: [PATCH 221/293] v2.0.rc9 --- busted-2.0.rc8-0.rockspec => busted-2.0.rc9-0.rockspec | 6 +++--- busted/core.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename busted-2.0.rc8-0.rockspec => busted-2.0.rc9-0.rockspec (97%) diff --git a/busted-2.0.rc8-0.rockspec b/busted-2.0.rc9-0.rockspec similarity index 97% rename from busted-2.0.rc8-0.rockspec rename to busted-2.0.rc9-0.rockspec index dda7dfbd..d8f294cc 100644 --- a/busted-2.0.rc8-0.rockspec +++ b/busted-2.0.rc9-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc8-0' +version = '2.0.rc9-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc8-0.tar.gz', - dir = 'busted-2.0.rc8-0' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc9-0.tar.gz', + dir = 'busted-2.0.rc9-0' } description = { summary = 'Elegant Lua unit testing.', diff --git a/busted/core.lua b/busted/core.lua index de79b198..9b9d96e7 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -44,7 +44,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc8-0' + busted.version = '2.0.rc9-0' local root = require 'busted.context'() busted.context = root.ref() From 536d407c7f49f6874064e01157caec3fe9064c3a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 30 May 2015 11:29:53 -0700 Subject: [PATCH 222/293] Remove ansicolors dependency from rockspec --- .luacov | 5 ++++- busted-2.0.rc9-0.rockspec | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.luacov b/.luacov index fd844951..f9b75eb0 100644 --- a/.luacov +++ b/.luacov @@ -38,7 +38,10 @@ return { 'luacov.runner$', 'luacov.stats$', 'luacov.tick$', - 'ansicolors$', + 'term$', + 'term.colors$', + 'term.cursor$', + 'term.init$', 'copas$', 'coxpcall$', 'mediator$', diff --git a/busted-2.0.rc9-0.rockspec b/busted-2.0.rc9-0.rockspec index d8f294cc..f002537c 100644 --- a/busted-2.0.rc9-0.rockspec +++ b/busted-2.0.rc9-0.rockspec @@ -24,7 +24,6 @@ dependencies = { 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.7-0', - 'ansicolors >= 1.0-1', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1.1-0', From 619891c008836914de48abe97c5229adc14f37f0 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 4 Jun 2015 23:59:47 -0700 Subject: [PATCH 223/293] Update osexit for LuaJIT Do not perform manual garbage collection if running a LuaJIT version that supports the `close` argument to `os.exit`. --- busted/compatibility.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index e7654fb4..8ccd5860 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -33,7 +33,8 @@ return { unpack = table.unpack or unpack, osexit = function(code, close) - if close and _VERSION == 'Lua 5.1' then + if close and _VERSION == 'Lua 5.1' and + (type(jit) ~= 'table' or not jit.version or jit.version_num < 20000) then -- From Lua 5.1 manual: -- > The userdata itself is freed only in the next -- > garbage-collection cycle. From 5e6d2eace572e313d32173794a5e8d060a77de31 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 5 Jun 2015 00:13:45 -0700 Subject: [PATCH 224/293] Update travis build to use LuaJIT v2.0.4 --- .travis_setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis_setup.sh b/.travis_setup.sh index 00ddeee0..a3e920a0 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -13,8 +13,8 @@ echo 'rocks_servers = { if [ "$LUA" == "LuaJIT 2.0" ]; then - wget -O - http://luajit.org/download/LuaJIT-2.0.3.tar.gz | tar xz - cd LuaJIT-2.0.3 + wget -O - http://luajit.org/download/LuaJIT-2.0.4.tar.gz | tar xz + cd LuaJIT-2.0.4 make && sudo make install INSTALL_TSYMNAME=lua; else if [ "$LUA" == "Lua 5.1" ]; then From aef8e27ed4a5d761eb80861b0e8ef1800876f267 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 9 Jun 2015 17:05:48 -0700 Subject: [PATCH 225/293] Fix error in building luarocks --- .travis_setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis_setup.sh b/.travis_setup.sh index a3e920a0..7b9d14c0 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -40,5 +40,5 @@ else ./configure; fi -make && sudo make install +make build && sudo make install cd .. From a6233a277da4e118f663606d54da8df88a27c076 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Sat, 20 Jun 2015 11:17:26 -0400 Subject: [PATCH 226/293] upgrade luassert, and v2.0.rc10 --- busted-2.0.rc9-0.rockspec => busted-2.0.rc10-0.rockspec | 8 ++++---- busted-scm-0.rockspec | 2 +- busted/core.lua | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename busted-2.0.rc9-0.rockspec => busted-2.0.rc10-0.rockspec (96%) diff --git a/busted-2.0.rc9-0.rockspec b/busted-2.0.rc10-0.rockspec similarity index 96% rename from busted-2.0.rc9-0.rockspec rename to busted-2.0.rc10-0.rockspec index f002537c..b9c541b2 100644 --- a/busted-2.0.rc9-0.rockspec +++ b/busted-2.0.rc10-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc9-0' +version = '2.0.rc10-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc9-0.tar.gz', - dir = 'busted-2.0.rc9-0' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc10-0.tar.gz', + dir = 'busted-2.0.rc10-0' } description = { summary = 'Elegant Lua unit testing.', @@ -23,7 +23,7 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', - 'luassert >= 1.7.7-0', + 'luassert >= 1.7.8-0', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1.1-0', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 79377faa..8b5e8543 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -23,7 +23,7 @@ dependencies = { 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', - 'luassert >= 1.7.7-0', + 'luassert >= 1.7.8-0', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1.1-0', diff --git a/busted/core.lua b/busted/core.lua index 9b9d96e7..a5209948 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -44,7 +44,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc9-0' + busted.version = '2.0.rc10-0' local root = require 'busted.context'() busted.context = root.ref() From 37589d8bb9dd8de0c9455c6cd0fdba9e31a2aa48 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Sat, 20 Jun 2015 11:26:16 -0400 Subject: [PATCH 227/293] Add olivine-labs manifest server path to travis file This way, when we update luassert / other dependencies, the travis builds don't fail while the changes propagate. (Still pulls from the official repo, it's just faster.) --- .travis_setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis_setup.sh b/.travis_setup.sh index 7b9d14c0..3f6cbede 100644 --- a/.travis_setup.sh +++ b/.travis_setup.sh @@ -5,6 +5,7 @@ set -e echo 'rocks_servers = { + "http://luarocks.org/manifests/olivine-labs", "http://rocks.moonscript.org/", "http://luarocks.org/repositories/rocks", "http://luarocks.logiceditor.com/rocks", From b7f643d1d11eadf22671f941fbba20798e160212 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 5 Jul 2015 13:32:34 -0700 Subject: [PATCH 228/293] Refactor default options --- bin/busted | 2 +- busted-2.0.rc10-0.rockspec | 1 + busted-scm-0.rockspec | 1 + busted/modules/cli.lua | 2 +- busted/options.lua | 4 ++++ busted/runner.lua | 3 ++- spec/modules/cli_spec.lua | 16 ++++++++-------- 7 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 busted/options.lua diff --git a/bin/busted b/bin/busted index 1184902c..706d530d 100755 --- a/bin/busted +++ b/bin/busted @@ -1,3 +1,3 @@ #!/usr/bin/env lua -- Busted command-line runner -require 'busted.runner'({ batch = true }) +require 'busted.runner'({ standalone = false }) diff --git a/busted-2.0.rc10-0.rockspec b/busted-2.0.rc10-0.rockspec index b9c541b2..28f7f206 100644 --- a/busted-2.0.rc10-0.rockspec +++ b/busted-2.0.rc10-0.rockspec @@ -36,6 +36,7 @@ build = { ['busted.context'] = 'busted/context.lua', ['busted.environment'] = 'busted/environment.lua', ['busted.compatibility'] = 'busted/compatibility.lua', + ['busted.options'] = 'busted/options.lua', ['busted.done'] = 'busted/done.lua', ['busted.runner'] = 'busted/runner.lua', ['busted.status'] = 'busted/status.lua', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 8b5e8543..bfcdbef0 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -36,6 +36,7 @@ build = { ['busted.context'] = 'busted/context.lua', ['busted.environment'] = 'busted/environment.lua', ['busted.compatibility'] = 'busted/compatibility.lua', + ['busted.options'] = 'busted/options.lua', ['busted.done'] = 'busted/done.lua', ['busted.runner'] = 'busted/runner.lua', ['busted.status'] = 'busted/status.lua', diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 8008841d..dde8d6d3 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -108,7 +108,7 @@ return function(options) -- Load up the command-line interface options cli:add_flag('--version', 'prints the program version and exits', false, processOption) - if options.batch then + if not options.standalone then cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 999, processArgList) cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) diff --git a/busted/options.lua b/busted/options.lua new file mode 100644 index 00000000..a3b62bfa --- /dev/null +++ b/busted/options.lua @@ -0,0 +1,4 @@ +return { + standalone = true, + defaultOutput = 'utfTerminal', +} diff --git a/busted/runner.lua b/busted/runner.lua index f41923f6..bbb77ac9 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -1,6 +1,7 @@ -- Busted command-line runner local path = require 'pl.path' +local tablex = require 'pl.tablex' local term = require 'term' local utils = require 'busted.utils' local osexit = require 'busted.compatibility'.osexit @@ -9,7 +10,7 @@ local loaded = false return function(options) if loaded then return else loaded = true end - local options = options or {} + options = tablex.update(require 'busted.options', options or {}) options.defaultOutput = term.isatty(io.stdout) and 'utfTerminal' or 'plainTerminal' local busted = require 'busted.core'() diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index ae7576f5..37b0e8fe 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -5,7 +5,7 @@ describe('Tests command-line interface', function() local defaultOutput = 'default_output_handler' local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) local args = cli:parse({}) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) @@ -59,7 +59,7 @@ describe('Tests command-line interface', function() end) it('standalone options disables ROOT and --pattern', function() - local cli = require 'busted.modules.cli'() + local cli = require 'busted.modules.cli'({ standalone = true }) local args = cli:parse({}) assert.is_nil(args.ROOT) assert.is_nil(args.p) @@ -197,7 +197,7 @@ describe('Tests command-line interface', function() end) it('specify ROOT arg and --pattern', function() - local cli = require 'busted.modules.cli'({ batch = true }) + local cli = require 'busted.modules.cli'({ standalone = false }) local args = cli:parse({ '-p', 'match_files', 'root_is_here' }) assert.is_same({'root_is_here'}, args.ROOT) assert.is_equal('match_files', args.p) @@ -205,7 +205,7 @@ describe('Tests command-line interface', function() end) it('specify multiple root paths', function() - local cli = require 'busted.modules.cli'({ batch = true }) + local cli = require 'busted.modules.cli'({ standalone = false }) local args = cli:parse({'root1_path', 'root2_path', 'root3_path'}) assert.is_same({'root1_path', 'root2_path', 'root3_path'}, args.ROOT) end) @@ -313,7 +313,7 @@ describe('Tests using .busted tasks', function() local defaultOutput = 'default_output_handler' local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden' }) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) @@ -370,7 +370,7 @@ describe('Tests using .busted tasks', function() local defaultOutput = 'default_output_handler' local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) local args = cli:parse({ '--config-file', 'spec/.hidden/.busted' }) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) @@ -424,7 +424,7 @@ describe('Tests using .busted tasks', function() end) it('load configuration options', function() - local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden', '--run=test' }) assert.is_equal('_test%.lua$', args.pattern) assert.is_same({'tests'}, args.ROOT) @@ -436,7 +436,7 @@ describe('Tests using .busted tasks', function() end) it('load configuration options and override with command-line', function() - local cli = require 'busted.modules.cli'({ batch = true, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--loaders=moonscript' }) assert.is_equal('patt', args.pattern) assert.is_same({'tag1'}, args.tags) From fd440f2fd2a64d3c2e5a95a16671259764fc519f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 5 Jul 2015 13:33:08 -0700 Subject: [PATCH 229/293] Refactor call to os.exit() Rename `compatibility.osexit` to `compatibility.exit`. Always close Lua state on call to `os.exit()`. --- busted/compatibility.lua | 6 +++--- busted/runner.lua | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 8ccd5860..225cd34a 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -32,8 +32,8 @@ return { unpack = table.unpack or unpack, - osexit = function(code, close) - if close and _VERSION == 'Lua 5.1' and + exit = function(code) + if _VERSION == 'Lua 5.1' and (type(jit) ~= 'table' or not jit.version or jit.version_num < 20000) then -- From Lua 5.1 manual: -- > The userdata itself is freed only in the next @@ -56,6 +56,6 @@ return { end end end - os.exit(code, close) + os.exit(code, true) end, } diff --git a/busted/runner.lua b/busted/runner.lua index bbb77ac9..cc18d49d 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -4,7 +4,7 @@ local path = require 'pl.path' local tablex = require 'pl.tablex' local term = require 'term' local utils = require 'busted.utils' -local osexit = require 'busted.compatibility'.osexit +local exit = require 'busted.compatibility'.exit local loaded = false return function(options) @@ -35,20 +35,20 @@ return function(options) local cliArgs, err = cli:parse(arg) if not cliArgs then io.stderr:write(err .. '\n') - osexit(1, true) + exit(1) end if cliArgs.version then -- Return early if asked for the version print(busted.version) - osexit(0, true) + exit(0) end -- Load current working directory local _, err = path.chdir(path.normpath(cliArgs.directory)) if err then io.stderr:write(appName .. ': error: ' .. err .. '\n') - osexit(1, true) + exit(1) end -- If coverage arg is passed in, load LuaCovsupport @@ -181,12 +181,12 @@ return function(options) busted.publish({ 'exit' }) - local exit = 0 + local code = 0 if failures > 0 or errors > 0 then - exit = failures + errors - if exit > 255 then - exit = 255 + code = failures + errors + if code > 255 then + code = 255 end end - osexit(exit, true) + exit(code) end From eaa9a37df4f0d596d327a704050f76c8cf7dcea9 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 5 Jul 2015 13:36:07 -0700 Subject: [PATCH 230/293] Use socket.gettime() to calculate suite duration --- busted/outputHandlers/base.lua | 6 ++++-- busted/outputHandlers/plainTerminal.lua | 4 ++-- busted/outputHandlers/utfTerminal.lua | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 13da5148..98b0a971 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -1,3 +1,5 @@ +local socket = require 'socket' + return function() local busted = require 'busted' local handler = { @@ -73,7 +75,7 @@ return function() end handler.baseSuiteStart = function() - handler.startTime = os.clock() + handler.startTime = socket.gettime() return nil, true end @@ -92,7 +94,7 @@ return function() end handler.baseSuiteEnd = function() - handler.endTime = os.clock() + handler.endTime = socket.gettime() return nil, true end diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 99276578..1378b71d 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -71,7 +71,7 @@ return function(options) local pendingString = s('output.pending_plural') local errorString = s('output.error_plural') - local ms = handler.getDuration() + local sec = handler.getDuration() local successes = handler.successesCount local pendings = handler.pendingsCount local failures = handler.failuresCount @@ -101,7 +101,7 @@ return function(options) errorString = s('output.error_single') end - local formattedTime = ('%.6f'):format(ms):gsub('([0-9])0+$', '%1') + local formattedTime = ('%.6f'):format(sec):gsub('([0-9])0+$', '%1') return successes .. ' ' .. successString .. ' / ' .. failures .. ' ' .. failureString .. ' / ' .. diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index b6470d14..3a2c0456 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -80,7 +80,7 @@ return function(options) local pendingString = s('output.pending_plural') local errorString = s('output.error_plural') - local ms = handler.getDuration() + local sec = handler.getDuration() local successes = handler.successesCount local pendings = handler.pendingsCount local failures = handler.failuresCount @@ -110,7 +110,7 @@ return function(options) errorString = s('output.error_single') end - local formattedTime = ('%.6f'):format(ms):gsub('([0-9])0+$', '%1') + local formattedTime = ('%.6f'):format(sec):gsub('([0-9])0+$', '%1') return colors.green(successes) .. ' ' .. successString .. ' / ' .. colors.red(failures) .. ' ' .. failureString .. ' / ' .. From f137b4adc503cbe95e00e8f55749e05f6d1bcfd5 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 10 Jul 2015 00:34:42 -0700 Subject: [PATCH 231/293] Refactor tests to use utils.executeex --- spec/cl_spec.lua | 373 ++++++++++------------------------ spec/insulate-expose_spec.lua | 13 +- 2 files changed, 119 insertions(+), 267 deletions(-) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index c693421c..85ed4b47 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -2,25 +2,6 @@ local utils = require 'pl.utils' local path = require 'pl.path' local normpath = path.normpath local busted_cmd = path.is_windows and 'lua bin/busted' or 'bin/busted' -local ditch = path.is_windows and ' 1> NUL 2>NUL' or ' > /dev/null 2>&1' - ---ditch = '' -- uncomment this line, to show output of failing commands, for debugging - -local error_started -local error_start = function() - if ditch ~= '' then return end - print('================================================') - print('== Error block follows ==') - print('================================================') - error_started = true -end -local error_end = function() - if ditch ~= '' then return end - print('================================================') - print('== Error block ended, all according to plan ==') - print('================================================') - error_started = false -end -- if exitcode >256, then take MSB as exit code local modexit = function(exitcode) @@ -32,165 +13,134 @@ local modexit = function(exitcode) end local execute = function(cmd) - local success, exitcode = utils.execute(cmd..ditch) - return not not success, modexit(exitcode) + local success, exitcode, out, err = utils.executeex(cmd) + return not not success, modexit(exitcode), out, err end -local run = function(cmd) - local p = io.popen(cmd, 'r') - local out = p:read('*a') - p:close() - return out +local executeBusted = function(args) + return execute(busted_cmd .. ' ' .. args) end +local executeLua = function(args) + return execute('lua ' .. args) +end -describe('Tests the busted command-line options', function() - - setup(function() - end) - - after_each(function() - if error_started then - print('================================================') - print('== Error block ended, something was wrong ==') - print('================================================') - error_started = false - end - end) - +describe('Tests the busted command-line options', function() it('tests running with --tags specified', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$') + success, exitcode = executeBusted('--pattern=_tags.lua$') assert.is_false(success) assert.is_equal(8, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1') + success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1,tag2') + success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1,tag2') assert.is_false(success) assert.is_equal(4, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1 --tags=tag2') + success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1 --tags=tag2') assert.is_false(success) assert.is_equal(4, exitcode) - error_end() end) it('tests running with --exclude-tags specified', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') + success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') + success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') assert.is_false(success) assert.is_equal(2, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --exclude-tags=tag2 --exclude-tags=dtag1,dtag2') + success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag2 --exclude-tags=dtag1,dtag2') assert.is_false(success) assert.is_equal(2, exitcode) - error_end() end) it('tests running with --tags and --exclude-tags specified', function () local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') + success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') assert.is_false(success) assert.is_equal(1, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') + success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) it('tests running with --tags specified in describe', function () local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=dtag1') + success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=dtag1') assert.is_false(success) assert.is_equal(5, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_tags.lua$ --tags=dtag2') + success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=dtag2') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) it('tests running with --filter specified', function () local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$') + success, exitcode = executeBusted('--pattern=_filter.lua$') assert.is_false(success) assert.is_equal(8, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern1"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern1"') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern2"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern2"') assert.is_false(success) assert.is_equal(2, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern1" --filter="pattern2"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern1" --filter="pattern2"') assert.is_false(success) assert.is_equal(4, exitcode) - error_end() end) it('tests running with --filter-out specified', function () local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="pattern1"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="pattern1"') assert.is_false(success) assert.is_equal(6, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="pattern%d"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="pattern%d"') assert.is_false(success) assert.is_equal(5, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="patt1" --filter-out="patt2"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="patt1" --filter-out="patt2"') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter-out="patt.*(%d)"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="patt.*(%d)"') assert.is_true(success) - error_end() end) it('tests running with --filter and --filter-out specified', function () local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') assert.is_true(success) - error_end() end) it('tests running with --filter specified in describe', function () local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="patt1"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="patt1"') assert.is_false(success) assert.is_equal(5, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=_filter.lua$ --filter="patt2"') + success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="patt2"') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) it('tests running with --lazy specified', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$') + success, exitcode = executeBusted('--lazy --pattern=_tags.lua$') assert.is_false(success) assert.is_equal(7, exitcode) - success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$ --tags=tag1') + success, exitcode = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1') assert.is_false(success) assert.is_equal(2, exitcode) - success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$ --tags=tag1,tag2') + success, exitcode = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1,tag2') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute(busted_cmd .. ' --lazy --pattern=_tags.lua$ --tags=tag1 --tags=tag2') + success, exitcode = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1 --tags=tag2') assert.is_false(success) assert.is_equal(3, exitcode) - error_end() end) it('tests running with -l specified', function() - local result = run(busted_cmd .. ' -l --pattern=cl_list.lua$') + local _, _, result = executeBusted('-l --pattern=cl_list.lua$') local expected = 'spec/cl_list.lua:4: Tests list test 1\n' .. 'spec/cl_list.lua:7: Tests list test 2\n' .. 'spec/cl_list.lua:10: Tests list test 3\n' @@ -198,7 +148,7 @@ describe('Tests the busted command-line options', function() end) it('tests running with --list specified', function() - local result = run(busted_cmd .. ' --list --pattern=cl_list.lua$') + local _, _, result = executeBusted('--list --pattern=cl_list.lua$') local expected = 'spec/cl_list.lua:4: Tests list test 1\n' .. 'spec/cl_list.lua:7: Tests list test 2\n' .. 'spec/cl_list.lua:10: Tests list test 3\n' @@ -207,83 +157,71 @@ describe('Tests the busted command-line options', function() it('tests running with --lpath specified', function() local success, exitcode - success, exitcode = execute(busted_cmd .. ' --lpath="spec/?.lua" spec/cl_lua_path.lua') + success, exitcode = executeBusted('--lpath="spec/?.lua" spec/cl_lua_path.lua') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests running with --lang specified', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=cl_success.lua$ --lang=en') + success, exitcode = executeBusted('--pattern=cl_success.lua$ --lang=en') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=cl_success --lang=not_found_here') + success, exitcode = executeBusted('--pattern=cl_success --lang=not_found_here') assert.is_false(success) assert.is_equal(1, exitcode) -- busted errors out on non-available language - error_end() end) it('tests running with --version specified', function() local success, exitcode - success, exitcode = execute(busted_cmd .. ' --version') + success, exitcode = executeBusted('--version') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests running with --help specified', function() local success, exitcode - success, exitcode = execute(busted_cmd .. ' --help') + success, exitcode = executeBusted('--help') assert.is_false(success) assert.is_equal(1, exitcode) end) it('tests running a non-compiling testfile', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=cl_compile_fail.lua$') + success, exitcode = executeBusted('--pattern=cl_compile_fail.lua$') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) it('tests running a testfile throwing errors when being run', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=cl_execute_fail.lua$') + success, exitcode = executeBusted('--pattern=cl_execute_fail.lua$') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) it('tests running with --output specified', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=cl_success.lua$ --output=TAP') + success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=TAP') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute(busted_cmd .. ' --pattern=cl_two_failures.lua$ --output=not_found_here') + success, exitcode = executeBusted('--pattern=cl_two_failures.lua$ --output=not_found_here') assert.is_false(success) assert.is_equal(3, exitcode) -- outputter missing, defaults to default outputter +1 error - error_end() end) it('tests running with --output specified with module in lua path', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') + success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') assert.is_true(success) assert.is_equal(0, exitcode) - error_end() end) it('tests no tests to exit with a fail-exitcode', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=this_filename_does_simply_not_exist$') + success, exitcode = executeBusted('--pattern=this_filename_does_simply_not_exist$') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) end) @@ -291,81 +229,69 @@ end) describe('Tests failing tests through the commandline', function() it('tests failing setup/before_each/after_each/teardown functions', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=cl_failing_support.lua$') + success, exitcode = executeBusted('--pattern=cl_failing_support.lua$') assert.is_false(success) assert.is_equal(16, exitcode) - error_end() end) it('tests failing support functions as errors', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_failing_support.lua$') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_failing_support.lua$') local _, numErrors = result:gsub('Error %-> .-\n','') assert.is_equal(16, numErrors) - error_end() end) end) describe('Test busted running standalone', function() it('tests running with --tags specified', function() local success, exitcode - error_start() - success, exitcode = execute('lua spec/cl_standalone.lua') + success, exitcode = executeLua('spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag1') + success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1') assert.is_false(success) assert.is_equal(2, exitcode) - success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag1,tag2') + success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1,tag2') assert.is_false(success) assert.is_equal(3, exitcode) - error_end() end) it('tests running with --exclude-tags specified', function() local success, exitcode - error_start() - success, exitcode = execute('lua spec/cl_standalone.lua --exclude-tags=tag1,tag2') + success, exitcode = executeLua('spec/cl_standalone.lua --exclude-tags=tag1,tag2') assert.is_true(success) assert.is_equal(0, exitcode) - success, exitcode = execute('lua spec/cl_standalone.lua --exclude-tags=tag2') + success, exitcode = executeLua('spec/cl_standalone.lua --exclude-tags=tag2') assert.is_false(success) assert.is_equal(2, exitcode) - error_end() end) it('tests running with --tags and --exclude-tags specified', function () local success, exitcode - error_start() - success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag1 --exclude-tags=tag1') + success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1 --exclude-tags=tag1') assert.is_false(success) assert.is_equal(1, exitcode) - success, exitcode = execute('lua spec/cl_standalone.lua --tags=tag3 --exclude-tags=tag4') + success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag3 --exclude-tags=tag4') assert.is_true(success) assert.is_equal(0, exitcode) - error_end() end) it('tests running with --helper specified', function () local success, exitcode - error_start() - success, exitcode = execute('lua spec/cl_standalone.lua --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown,--fail-after-each"') + success, exitcode = executeLua('spec/cl_standalone.lua --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown,--fail-after-each"') assert.is_false(success) assert.is_equal(9, exitcode) - error_end() end) it('tests running with --version specified', function() local success, exitcode - success, exitcode = execute('lua spec/cl_standalone.lua --version') + success, exitcode = executeLua('spec/cl_standalone.lua --version') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests running with --help specified', function() local success, exitcode - success, exitcode = execute('lua spec/cl_standalone.lua --help') + success, exitcode = executeLua('spec/cl_standalone.lua --help') assert.is_false(success) assert.is_equal(1, exitcode) end) @@ -374,191 +300,155 @@ end) describe('Test busted command-line runner', function() it('runs standalone spec', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' spec/cl_standalone.lua') + success, exitcode = executeBusted('spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, exitcode) - success, exitcode = execute(busted_cmd .. ' --tags=tag1 spec/cl_standalone.lua') + success, exitcode = executeBusted('--tags=tag1 spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(2, exitcode) - success, exitcode = execute(busted_cmd .. ' --tags=tag1,tag2 spec/cl_standalone.lua') + success, exitcode = executeBusted('--tags=tag1,tag2 spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, exitcode) - error_end() end) end) describe('Tests distinguish between errors and failures', function() it('by detecting errors as test errors', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') local errmsg = result:match('(Error %-> .-)\n') assert.is_truthy(errmsg) - error_end() end) it('by detecting assert failures as test failures', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_two_failures.lua$') local failmsg = result:match('(Failure %-> .-)\n') assert.is_truthy(failmsg) - error_end() end) it('by detecting Lua runtime errors as test errors', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=luaerr') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_errors.lua$ --tags=luaerr') local failmsg = result:match('(Error %-> .-)\n') assert.is_truthy(failmsg) - error_end() end) end) describe('Tests stack trackback', function() it('when throwing an error', function() - error_start() - local result = run(busted_cmd .. ' --verbose --pattern=cl_errors.lua$ --tags=testerr') + local _, _, result = executeBusted('--verbose --pattern=cl_errors.lua$ --tags=testerr') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: spec/cl_errors.lua:6: in function ]] assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when assertion fails', function() - error_start() - local result = run(busted_cmd .. ' --verbose --pattern=cl_two_failures.lua$ --tags=err1') + local _, _, result = executeBusted('--verbose --pattern=cl_two_failures.lua$ --tags=err1') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: spec/cl_two_failures.lua:6: in function ]] assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when Lua runtime error', function() - error_start() - local result = run(busted_cmd .. ' --verbose --pattern=cl_errors.lua$ --tags=luaerr') + local _, _, result = executeBusted('--verbose --pattern=cl_errors.lua$ --tags=luaerr') local errmsg = result:match('(stack traceback:.*)\n') local expected = [[stack traceback: spec/cl_errors.lua:11: in function ]] assert.is_equal(normpath(expected), errmsg) - error_end() end) end) describe('Tests error messages through the command line', function() it('when throwing errors in a test', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_errors.lua$ --tags=testerr') local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(spec[/\\].-)\n') local expectedErr = "Error -> spec/cl_errors.lua @ 5" local expectedMsg = "spec/cl_errors.lua:6: force an error" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) - error_end() end) it('when throwing an error table', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --tags=table --pattern=cl_error_messages.lua$') + local _, _, result = executeBusted('--output=plainTerminal --tags=table --pattern=cl_error_messages.lua$') local errmsg = result:match('\n(spec[/\\].-)\n') local expected = 'spec/cl_error_messages.lua:5: {' assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when throwing a nil error', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --tags=nil --pattern=cl_error_messages.lua$') + local _, _, result = executeBusted('--output=plainTerminal --tags=nil --pattern=cl_error_messages.lua$') local errmsg = result:match('\n(spec[/\\].-)\n') local expected = 'spec/cl_error_messages.lua:9: Nil error' assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when throwing an error table with __tostring', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --tags=tostring --pattern=cl_error_messages.lua$') + local _, _, result = executeBusted('--output=plainTerminal --tags=tostring --pattern=cl_error_messages.lua$') local errmsg = result:match('\n(spec[/\\].-)\n') local expected = 'spec/cl_error_messages.lua:17: {}' assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when throwing after a pcall', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --tags=pcall --pattern=cl_error_messages.lua$') + local _, _, result = executeBusted('--output=plainTerminal --tags=pcall --pattern=cl_error_messages.lua$') local errmsg = result:match('\n(spec[/\\].-)\n') local expected = 'spec/cl_error_messages.lua:22: error after pcall' assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when running a non-compiling testfile', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_compile_fail.lua$') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_compile_fail.lua$') local errmsg = result:match('(Error %-> .-:%d+:) ') local expected = "Error -> spec/cl_compile_fail.lua:3:" assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when a testfile throws errors', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_execute_fail.lua$') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_execute_fail.lua$') local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(spec[/\\]cl_execute_fail%.lua:%d+:.-)\n') local expectedErr = 'Error -> spec/cl_execute_fail.lua @ 4' local expectedMsg = 'spec/cl_execute_fail.lua:4: This compiles fine, but throws an error when being run' assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) - error_end() end) it('when output library not found', function() - error_start() - local result = run(busted_cmd .. ' --pattern=cl_two_failures.lua$ --output=not_found_here 2>&1') - local errmsg = result:match('(.-)\n') + local _, _, result, rerr = executeBusted('--pattern=cl_two_failures.lua$ --output=not_found_here 2>&1') + local errmsg = rerr:match('(.-)\n') local expected = 'busted: error: Cannot load output library: not_found_here' assert.is_equal(expected, errmsg) - error_end() end) it('when helper script not found', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here 2>&1') + local _, _, result, rerr = executeBusted('--output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here 2>&1') local err = result:match('Error %-> .-:%d+: (.-)\n') - local errmsg = result:match('(.-)\n') + local errmsg = rerr:match('(.-)\n') local expectedErr = "module 'not_found_here' not found:" local expectedMsg = 'busted: error: Cannot load helper script: not_found_here' assert.is_equal(expectedErr, err) assert.is_equal(expectedMsg, errmsg) - error_end() end) it('when helper lua script not found', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua 2>&1') + local _, _, result, rerr = executeBusted('--output=plainTerminal --pattern=cl_two_failures.lua$ --helper=not_found_here.lua 2>&1') local err = result:match('Error %-> (.-)\n') - local errmsg = result:match('(.-)\n') + local errmsg = rerr:match('(.-)\n') local expectedErr = 'cannot open not_found_here.lua: No such file or directory' local expectedMsg = 'busted: error: Cannot load helper script: not_found_here.lua' - assert.is_equal(normpath(expectedErr), err) + assert.is_equal(expectedErr, err) assert.is_equal(expectedMsg, errmsg) - error_end() end) it('when no test files matching Lua pattern', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=this_filename_does_simply_not_exist$') + local _, _, result = executeBusted('--output=plainTerminal --pattern=this_filename_does_simply_not_exist$') local errmsg = result:match('Error %-> (.-)\n') local expected = 'No test files found matching Lua pattern: this_filename_does_simply_not_exist$' assert.is_equal(expected, errmsg) - error_end() end) end) @@ -567,126 +457,101 @@ local describe_moon = (has_moon and describe or pending) describe_moon('Tests moonscript error messages through the command line', function() it('when assertion fails', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=fail') local err = result:match('(Failure %-> .-)\n') local errmsg = result:match('\n(spec[/\\].-)\n') local expectedErr = "Failure -> spec/cl_moonscript_error_messages.moon @ 4" local expectedMsg = "spec/cl_moonscript_error_messages.moon:5: Expected objects to be equal." assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) - error_end() end) it('when throwing string errors', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_moonscript_error_messages.moon$ --tags=string') local err = result:match('(Error %-> .-)\n') local errmsg = result:match('\n(spec[/\\].-)\n') local expectedErr = "Error -> spec/cl_moonscript_error_messages.moon @ 16" local expectedMsg = "spec/cl_moonscript_error_messages.moon:17: error message" assert.is_equal(normpath(expectedErr), err) assert.is_equal(normpath(expectedMsg), errmsg) - error_end() end) it('when throwing an error table', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --tags=table --pattern=cl_moonscript_error_messages.moon$') + local _, _, result = executeBusted('--output=plainTerminal --tags=table --pattern=cl_moonscript_error_messages.moon$') local errmsg = result:match('\n(spec[/\\].-)\n') local expected = 'spec/cl_moonscript_error_messages.moon:9: {' assert.is_equal(normpath(expected), errmsg) - error_end() end) it('when throwing a nil error', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --tags=nil --pattern=cl_moonscript_error_messages.moon$') + local _, _, result = executeBusted('--output=plainTerminal --tags=nil --pattern=cl_moonscript_error_messages.moon$') local errmsg = result:match('\n(spec[/\\].-)\n') local expected = 'spec/cl_moonscript_error_messages.moon:13: Nil error' assert.is_equal(normpath(expected), errmsg) - error_end() end) end) describe('Tests pending through the commandline', function() it('skips tests inside pending scope', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --pattern=cl_pending.lua$') + success, exitcode = executeBusted('--pattern=cl_pending.lua$') assert.is_true(success) assert.is_equal(0, exitcode) - error_end() end) it('detects tests as pending', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --pattern=cl_pending.lua$') + local _, _, result = executeBusted('--output=plainTerminal --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') local _, numPending = result:gsub('Pending %-> .-\n', '') assert.is_equal(2, pendingDots) assert.is_equal(2, numPending) - error_end() end) it('--suppress-pending option is honored', function() - error_start() - local result = run(busted_cmd .. ' --output=plainTerminal --suppress-pending --pattern=cl_pending.lua$') + local _, _, result = executeBusted('--output=plainTerminal --suppress-pending --pattern=cl_pending.lua$') local line1 = result:match('.-\n') local _, pendingDots = line1:gsub('%.', '') local _, numPending = result:gsub('Pending %-> .-\n', '') assert.is_equal(0, pendingDots) assert.is_equal(0, numPending) - error_end() end) end) describe('Tests random seed through the commandline', function() it('test seed value', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --seed=12345 --pattern=cl_random_seed.lua$') + success, exitcode = executeBusted('--seed=12345 --pattern=cl_random_seed.lua$') assert.is_true(success) assert.is_equal(0, exitcode) - error_end() end) it('test invalid seed value exits with error', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --seed=abcd --pattern=cl_random_seed.lua$') + success, exitcode = executeBusted('--seed=abcd --pattern=cl_random_seed.lua$') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) it('test failure outputs random seed value', function() - error_start() - local result = run(busted_cmd .. ' --seed=789 --pattern=cl_random_seed.lua$') + local _, _, result = executeBusted('--seed=789 --pattern=cl_random_seed.lua$') local seed = result:match('Random seed: (%d+)\n') assert.is_equal(789, tonumber(seed)) - error_end() end) it('test non-randomized failure does not output seed value', function() - error_start() - local result = run(busted_cmd .. ' --seed=789 --pattern=cl_two_failures.lua$') + local _, _, result = executeBusted('--seed=789 --pattern=cl_two_failures.lua$') local seed = result:match('Random seed:') assert.is_equal(nil, seed) - error_end() end) end) describe('Tests shuffle commandline option', function() for _, opt in ipairs({ '--shuffle', '--shuffle-tests' }) do it('forces test shuffling for non-randomized tests, ' .. opt, function() - local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' ' .. opt .. ' --pattern=cl_randomize.lua$') + local success, exitcode = executeBusted(opt .. ' --pattern=cl_randomize.lua$') assert.is_true(success) assert.is_equal(0, exitcode) - error_end() end) end end) @@ -695,11 +560,9 @@ describe('Tests sort commandline option', function() for _, opt in ipairs({ '--sort', '--sort-tests' }) do it('sorts tests by name, ' .. opt, function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' ' .. opt .. ' --pattern=cl_sort.lua$') + success, exitcode = executeBusted(opt .. ' --pattern=cl_sort.lua$') assert.is_true(success) assert.is_equal(0, exitcode) - error_end() end) end end) @@ -707,77 +570,67 @@ end) describe('Tests repeat commandline option', function() it('forces tests to repeat n times', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --repeat=2 --pattern=cl_two_failures.lua$') + success, exitcode = executeBusted('--repeat=2 --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(4, exitcode) - error_end() end) it('exits with error when repeat is invalid', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --repeat=abc --pattern=cl_success.lua$') + success, exitcode = executeBusted('--repeat=abc --pattern=cl_success.lua$') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) end) describe('Tests no-keep-going commandline option', function() it('skips all tests after first error', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --no-keep-going --pattern=cl_two_failures.lua$') + success, exitcode = executeBusted('--no-keep-going --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) end) describe('Tests no-recursive commandline option', function() it('does not run any tests in subdirectories', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --no-recursive --pattern=cl_two_failures.lua$ .') + success, exitcode = executeBusted('--no-recursive --pattern=cl_two_failures.lua$ .') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) end) describe('Tests no-auto-insulate commandline option', function() it('does not insulate test files', function() local success, exitcode - error_start() - success, exitcode = execute(busted_cmd .. ' --no-auto-insulate --pattern=insulate_file.*.lua$') + success, exitcode = executeBusted('--no-auto-insulate --pattern=insulate_file.*.lua$') assert.is_false(success) assert.is_equal(1, exitcode) - error_end() end) end) describe('Tests Xoutput commandline option', function() it('forwards no options to output handler when no options specified', function() - local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua --pattern=cl_success.lua$') + local _, _, result = executeBusted('--output=spec/cl_output_handler.lua --pattern=cl_success.lua$') local status = result:match('^%[(.-)]') assert.is_equal(' success', status) end) it('forwards single option to output handler', function() - local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua -Xoutput "--time" --pattern=cl_success.lua$') + local _, _, result = executeBusted('--output=spec/cl_output_handler.lua -Xoutput "--time" --pattern=cl_success.lua$') local timestamp = result:match('^%[(.-)]') assert.is_equal('Fri Jan 2 10:17:36 1970', timestamp) end) it('forwards multiple options to output handler', function() - local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua -Xoutput "--time,--time-format=!%H:%M:%S" --pattern=cl_success.lua$') + local _, _, result = executeBusted('--output=spec/cl_output_handler.lua -Xoutput "--time,--time-format=!%H:%M:%S" --pattern=cl_success.lua$') local timestamp = result:match('^%[(.-)]') assert.is_equal('10:17:36', timestamp) end) it('forwards multiple options to output handler using multiple -Xoutput', function() - local result = run(busted_cmd .. ' --output=spec/cl_output_handler.lua -Xoutput "--time" -Xoutput "--time-format=!%H:%M:%S" --pattern=cl_success.lua$') + local _, _, result = executeBusted('--output=spec/cl_output_handler.lua -Xoutput "--time" -Xoutput "--time-format=!%H:%M:%S" --pattern=cl_success.lua$') local timestamp = result:match('^%[(.-)]') assert.is_equal('10:17:36', timestamp) end) @@ -785,24 +638,24 @@ end) describe('Tests Xhelper commandline option', function() it('forwards no options to helper script when no options specified', function() - local success = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua --pattern=cl_success.lua$') + local success = executeBusted('--helper=spec/cl_helper_script.lua --pattern=cl_success.lua$') assert.is_true(success) end) it('forwards single option to helper script', function() - local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" --pattern=cl_success.lua$') + local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" --pattern=cl_success.lua$') assert.is_false(success) assert.is_equal(1, exitcode) end) it('forwards multiple options to helper script', function() - local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each,--fail-after-each" --pattern=cl_success.lua$') + local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each,--fail-after-each" --pattern=cl_success.lua$') assert.is_false(success) assert.is_equal(2, exitcode) end) it('forwards multiple options to helper script using multiple -Xhelper', function() - local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" -Xhelper "--fail-after-each" --pattern=cl_success.lua$') + local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" -Xhelper "--fail-after-each" --pattern=cl_success.lua$') assert.is_false(success) assert.is_equal(2, exitcode) end) @@ -810,25 +663,25 @@ end) describe('Tests helper script', function() it('can add setup to test suite', function() - local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup" --pattern=cl_two_failures.lua$') + local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-setup" --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(1, exitcode) end) it('can add teardown to test suite', function() - local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown" --pattern=cl_two_failures.lua$') + local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown" --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(3, exitcode) end) it('runs setup/teardown for mutiple runs', function() - local success, exitcode = execute(busted_cmd .. ' --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') + local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') assert.is_false(success) assert.is_equal(4, exitcode) end) it('runs setup/teardown for mutiple runs with --lazy', function() - local success, exitcode = execute(busted_cmd .. ' --lazy --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') + local success, exitcode = executeBusted('--lazy --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') assert.is_false(success) assert.is_equal(4, exitcode) end) diff --git a/spec/insulate-expose_spec.lua b/spec/insulate-expose_spec.lua index acccc38d..0409a3d1 100644 --- a/spec/insulate-expose_spec.lua +++ b/spec/insulate-expose_spec.lua @@ -117,25 +117,24 @@ describe('Tests insulate/expose', function() local path = require 'pl.path' local utils = require 'pl.utils' local busted_cmd = path.is_windows and 'lua bin/busted' or 'bin/busted' - local ditch = path.is_windows and ' 1> NUL 2>NUL' or ' > /dev/null 2>&1' - local execute = function(cmd) - local success, exitcode = utils.execute(cmd..ditch) + local executeBusted = function(args) + local success, exitcode, out, err = utils.executeex(busted_cmd .. ' ' .. args) if exitcode > 255 then exitcode = math.floor(exitcode/256), exitcode - math.floor(exitcode/256)*256 end - return not not success, exitcode + return not not success, exitcode, out, err end describe('file insulation', function() it('works between files', function() - local success, exitcode = execute(busted_cmd .. ' spec/insulate_file1.lua spec/insulate_file2.lua') + local success, exitcode = executeBusted('spec/insulate_file1.lua spec/insulate_file2.lua') assert.is_true(success) assert.is_equal(0, exitcode) end) it('works between files independent of order', function() - local success, exitcode = execute(busted_cmd .. ' spec/insulate_file2.lua spec/insulate_file1.lua') + local success, exitcode = executeBusted('spec/insulate_file2.lua spec/insulate_file1.lua') assert.is_true(success) assert.is_equal(0, exitcode) end) @@ -143,7 +142,7 @@ describe('Tests insulate/expose', function() describe('expose from file context', function() it('works between files', function() - local success, exitcode = execute(busted_cmd .. ' spec/expose_file1.lua spec/expose_file2.lua') + local success, exitcode = executeBusted('spec/expose_file1.lua spec/expose_file2.lua') assert.is_true(success) assert.is_equal(0, exitcode) end) From 4a477a4d8dbef12cbe93022655ef898b69329662 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 10 Jul 2015 01:29:16 -0700 Subject: [PATCH 232/293] Refactor exit code Always return 1 on error and 0 on success. Throw an `error` to exit with error whenever possible. --- busted/compatibility.lua | 3 +- busted/runner.lua | 11 +--- spec/cl_spec.lua | 118 +++++++++++++++------------------------ 3 files changed, 49 insertions(+), 83 deletions(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 225cd34a..f80b0dc4 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -33,6 +33,7 @@ return { unpack = table.unpack or unpack, exit = function(code) + if code ~= 0 then error() end if _VERSION == 'Lua 5.1' and (type(jit) ~= 'table' or not jit.version or jit.version_num < 20000) then -- From Lua 5.1 manual: @@ -56,6 +57,6 @@ return { end end end - os.exit(code, true) + os.exit(0, true) end, } diff --git a/busted/runner.lua b/busted/runner.lua index cc18d49d..f3b5e0fb 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -168,7 +168,7 @@ return function(options) testFileLoader(rootFiles, pattern, testFileLoaderOptions) -- If running standalone, setup test file to be compatible with live coding - if not cliArgs.ROOT then + if options.standalone then local ctx = busted.context.get() local children = busted.context.children(ctx) local file = children[#children] @@ -181,12 +181,7 @@ return function(options) busted.publish({ 'exit' }) - local code = 0 - if failures > 0 or errors > 0 then - code = failures + errors - if code > 255 then - code = 255 - end + if options.standalone or failures > 0 or errors > 0 then + exit(failures + errors) end - exit(code) end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 85ed4b47..9cd888af 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -18,18 +18,27 @@ local execute = function(cmd) end local executeBusted = function(args) - return execute(busted_cmd .. ' ' .. args) + local success, exitcode, out, err = execute(busted_cmd .. ' ' .. args) + local count = 0 + for failures, errors in out:gmatch('(%d+) failures? / (%d+) errors?') do + count = count + failures + errors + end + return success, count, out, err end local executeLua = function(args) - return execute('lua ' .. args) + local success, exitcode, out, err = execute('lua ' .. args) + local count = 0 + for failures, errors in out:gmatch('(%d+) failures? / (%d+) errors?') do + count = count + failures + errors + end + return success, count, out, err end describe('Tests the busted command-line options', function() it('tests running with --tags specified', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=_tags.lua$') + local success, exitcode = executeBusted('--pattern=_tags.lua$') assert.is_false(success) assert.is_equal(8, exitcode) success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1') @@ -44,8 +53,7 @@ describe('Tests the busted command-line options', function() end) it('tests running with --exclude-tags specified', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') + local success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') assert.is_true(success) assert.is_equal(0, exitcode) success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') @@ -57,18 +65,14 @@ describe('Tests the busted command-line options', function() end) it('tests running with --tags and --exclude-tags specified', function () - local success, exitcode - success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') + local success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') assert.is_false(success) - assert.is_equal(1, exitcode) success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') assert.is_false(success) - assert.is_equal(1, exitcode) end) it('tests running with --tags specified in describe', function () - local success, exitcode - success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=dtag1') + local success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=dtag1') assert.is_false(success) assert.is_equal(5, exitcode) success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=dtag2') @@ -77,8 +81,7 @@ describe('Tests the busted command-line options', function() end) it('tests running with --filter specified', function () - local success, exitcode - success, exitcode = executeBusted('--pattern=_filter.lua$') + local success, exitcode = executeBusted('--pattern=_filter.lua$') assert.is_false(success) assert.is_equal(8, exitcode) success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern1"') @@ -93,8 +96,7 @@ describe('Tests the busted command-line options', function() end) it('tests running with --filter-out specified', function () - local success, exitcode - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="pattern1"') + local success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="pattern1"') assert.is_false(success) assert.is_equal(6, exitcode) success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="pattern%d"') @@ -108,14 +110,12 @@ describe('Tests the busted command-line options', function() end) it('tests running with --filter and --filter-out specified', function () - local success, exitcode - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') + local success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') assert.is_true(success) end) it('tests running with --filter specified in describe', function () - local success, exitcode - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="patt1"') + local success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="patt1"') assert.is_false(success) assert.is_equal(5, exitcode) success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="patt2"') @@ -124,8 +124,7 @@ describe('Tests the busted command-line options', function() end) it('tests running with --lazy specified', function() - local success, exitcode - success, exitcode = executeBusted('--lazy --pattern=_tags.lua$') + local success, exitcode = executeBusted('--lazy --pattern=_tags.lua$') assert.is_false(success) assert.is_equal(7, exitcode) success, exitcode = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1') @@ -156,70 +155,59 @@ describe('Tests the busted command-line options', function() end) it('tests running with --lpath specified', function() - local success, exitcode - success, exitcode = executeBusted('--lpath="spec/?.lua" spec/cl_lua_path.lua') + local success, exitcode = executeBusted('--lpath="spec/?.lua" spec/cl_lua_path.lua') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests running with --lang specified', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=cl_success.lua$ --lang=en') + local success, exitcode = executeBusted('--pattern=cl_success.lua$ --lang=en') assert.is_true(success) assert.is_equal(0, exitcode) success, exitcode = executeBusted('--pattern=cl_success --lang=not_found_here') assert.is_false(success) - assert.is_equal(1, exitcode) -- busted errors out on non-available language end) it('tests running with --version specified', function() - local success, exitcode - success, exitcode = executeBusted('--version') + local success, exitcode = executeBusted('--version') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests running with --help specified', function() - local success, exitcode - success, exitcode = executeBusted('--help') + local success, exitcode = executeBusted('--help') assert.is_false(success) - assert.is_equal(1, exitcode) end) it('tests running a non-compiling testfile', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=cl_compile_fail.lua$') + local success, exitcode = executeBusted('--pattern=cl_compile_fail.lua$') assert.is_false(success) assert.is_equal(1, exitcode) end) it('tests running a testfile throwing errors when being run', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=cl_execute_fail.lua$') + local success, exitcode = executeBusted('--pattern=cl_execute_fail.lua$') assert.is_false(success) assert.is_equal(1, exitcode) end) it('tests running with --output specified', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=TAP') + local success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=TAP') assert.is_true(success) assert.is_equal(0, exitcode) success, exitcode = executeBusted('--pattern=cl_two_failures.lua$ --output=not_found_here') assert.is_false(success) - assert.is_equal(3, exitcode) -- outputter missing, defaults to default outputter +1 error + assert.is_equal(2, exitcode) end) it('tests running with --output specified with module in lua path', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') + local success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests no tests to exit with a fail-exitcode', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=this_filename_does_simply_not_exist$') + local success, exitcode = executeBusted('--pattern=this_filename_does_simply_not_exist$') assert.is_false(success) assert.is_equal(1, exitcode) end) @@ -228,8 +216,7 @@ end) describe('Tests failing tests through the commandline', function() it('tests failing setup/before_each/after_each/teardown functions', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=cl_failing_support.lua$') + local success, exitcode = executeBusted('--pattern=cl_failing_support.lua$') assert.is_false(success) assert.is_equal(16, exitcode) end) @@ -243,8 +230,7 @@ end) describe('Test busted running standalone', function() it('tests running with --tags specified', function() - local success, exitcode - success, exitcode = executeLua('spec/cl_standalone.lua') + local success, exitcode = executeLua('spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, exitcode) success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1') @@ -256,8 +242,7 @@ describe('Test busted running standalone', function() end) it('tests running with --exclude-tags specified', function() - local success, exitcode - success, exitcode = executeLua('spec/cl_standalone.lua --exclude-tags=tag1,tag2') + local success, exitcode = executeLua('spec/cl_standalone.lua --exclude-tags=tag1,tag2') assert.is_true(success) assert.is_equal(0, exitcode) success, exitcode = executeLua('spec/cl_standalone.lua --exclude-tags=tag2') @@ -266,41 +251,33 @@ describe('Test busted running standalone', function() end) it('tests running with --tags and --exclude-tags specified', function () - local success, exitcode - success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1 --exclude-tags=tag1') + local success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1 --exclude-tags=tag1') assert.is_false(success) - assert.is_equal(1, exitcode) success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag3 --exclude-tags=tag4') assert.is_true(success) - assert.is_equal(0, exitcode) end) it('tests running with --helper specified', function () - local success, exitcode - success, exitcode = executeLua('spec/cl_standalone.lua --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown,--fail-after-each"') + local success, exitcode = executeLua('spec/cl_standalone.lua --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown,--fail-after-each"') assert.is_false(success) assert.is_equal(9, exitcode) end) it('tests running with --version specified', function() - local success, exitcode - success, exitcode = executeLua('spec/cl_standalone.lua --version') + local success, exitcode = executeLua('spec/cl_standalone.lua --version') assert.is_true(success) assert.is_equal(0, exitcode) end) it('tests running with --help specified', function() - local success, exitcode - success, exitcode = executeLua('spec/cl_standalone.lua --help') + local success, exitcode = executeLua('spec/cl_standalone.lua --help') assert.is_false(success) - assert.is_equal(1, exitcode) end) end) describe('Test busted command-line runner', function() it('runs standalone spec', function() - local success, exitcode - success, exitcode = executeBusted('spec/cl_standalone.lua') + local success, exitcode = executeBusted('spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, exitcode) success, exitcode = executeBusted('--tags=tag1 spec/cl_standalone.lua') @@ -530,7 +507,6 @@ describe('Tests random seed through the commandline', function() local success, exitcode success, exitcode = executeBusted('--seed=abcd --pattern=cl_random_seed.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) end) it('test failure outputs random seed value', function() @@ -559,8 +535,7 @@ end) describe('Tests sort commandline option', function() for _, opt in ipairs({ '--sort', '--sort-tests' }) do it('sorts tests by name, ' .. opt, function() - local success, exitcode - success, exitcode = executeBusted(opt .. ' --pattern=cl_sort.lua$') + local success, exitcode = executeBusted(opt .. ' --pattern=cl_sort.lua$') assert.is_true(success) assert.is_equal(0, exitcode) end) @@ -569,8 +544,7 @@ end) describe('Tests repeat commandline option', function() it('forces tests to repeat n times', function() - local success, exitcode - success, exitcode = executeBusted('--repeat=2 --pattern=cl_two_failures.lua$') + local success, exitcode = executeBusted('--repeat=2 --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(4, exitcode) end) @@ -579,14 +553,12 @@ describe('Tests repeat commandline option', function() local success, exitcode success, exitcode = executeBusted('--repeat=abc --pattern=cl_success.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) end) end) describe('Tests no-keep-going commandline option', function() it('skips all tests after first error', function() - local success, exitcode - success, exitcode = executeBusted('--no-keep-going --pattern=cl_two_failures.lua$') + local success, exitcode = executeBusted('--no-keep-going --pattern=cl_two_failures.lua$') assert.is_false(success) assert.is_equal(1, exitcode) end) @@ -594,8 +566,7 @@ end) describe('Tests no-recursive commandline option', function() it('does not run any tests in subdirectories', function() - local success, exitcode - success, exitcode = executeBusted('--no-recursive --pattern=cl_two_failures.lua$ .') + local success, exitcode = executeBusted('--no-recursive --pattern=cl_two_failures.lua$ .') assert.is_false(success) assert.is_equal(1, exitcode) end) @@ -603,8 +574,7 @@ end) describe('Tests no-auto-insulate commandline option', function() it('does not insulate test files', function() - local success, exitcode - success, exitcode = executeBusted('--no-auto-insulate --pattern=insulate_file.*.lua$') + local success, exitcode = executeBusted('--no-auto-insulate --pattern=insulate_file.*.lua$') assert.is_false(success) assert.is_equal(1, exitcode) end) From e082261ceb7fa0908f62a371f255617486774247 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 17 Jul 2015 12:35:57 -0700 Subject: [PATCH 233/293] Fix file test count for gtest output --- busted/outputHandlers/gtest.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index b6167601..bc6f881d 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -54,6 +54,7 @@ return function(options) } local fileCount = 0 + local fileTestCount = 0 local testCount = 0 local successCount = 0 local skippedCount = 0 @@ -160,6 +161,7 @@ return function(options) handler.suiteReset = function() fileCount = 0 + fileTestCount = 0 testCount = 0 successCount = 0 skippedCount = 0 @@ -198,6 +200,7 @@ return function(options) handler.fileStart = function(file) fileStartTime = socket.gettime() + fileTestCount = 0 io.write(fileStartString:format(file.name)) io.flush() return nil, true @@ -205,9 +208,9 @@ return function(options) handler.fileEnd = function(file) local elapsedTime_ms = (socket.gettime() - fileStartTime) * 1000 - local tests = (testCount == 1 and 'test' or 'tests') + local tests = (fileTestCount == 1 and 'test' or 'tests') fileCount = fileCount + 1 - io.write(fileEndString:format(testCount, tests, file.name, elapsedTime_ms)) + io.write(fileEndString:format(fileTestCount, tests, file.name, elapsedTime_ms)) io.flush() return nil, true end @@ -224,6 +227,7 @@ return function(options) local elapsedTime_ms = (socket.gettime() - testStartTime) * 1000 local string + fileTestCount = fileTestCount + 1 testCount = testCount + 1 if status == 'success' then successCount = successCount + 1 From e55b496585389a4a46b4820a9d43b1b866130b16 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 18 Aug 2015 12:13:26 -0700 Subject: [PATCH 234/293] Fix json output Looks like the json module has issues with tables that have functions in them. So remove output tables that have functions. --- busted/outputHandlers/base.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 98b0a971..6690b611 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -55,13 +55,17 @@ return function() handler.format = function(element, parent, message, debug, isError) local formatted = { trace = debug or element.trace, - element = element, + element = { + name = element.name, + descriptor = element.descriptor, + attributes = element.attributes, + trace = element.trace or debug, + }, name = handler.getFullName(element), message = message, randomseed = parent and parent.randomseed, isError = isError } - formatted.element.trace = element.trace or debug return formatted end From 727c0fe67f83dad0ae98bed61078baac24669bce Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 17 Aug 2015 13:49:42 -0700 Subject: [PATCH 235/293] Handle errors from __gc metamethods --- busted/core.lua | 5 +++++ spec/cl_gc_error.lua | 9 +++++++++ spec/cl_spec.lua | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 spec/cl_gc_error.lua diff --git a/busted/core.lua b/busted/core.lua index a5209948..b68037d2 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -173,6 +173,11 @@ return function() end) } if not ret[1] then + if status == 'success' then + status = 'error' + trace = busted.getTrace(element, 3, ret[2]) + message = busted.rewriteMessage(element, ret[2], trace) + end busted.publish({ status, descriptor }, element, busted.context.parent(element), message, trace) end ret[1] = busted.status(status) diff --git a/spec/cl_gc_error.lua b/spec/cl_gc_error.lua new file mode 100644 index 00000000..248ba835 --- /dev/null +++ b/spec/cl_gc_error.lua @@ -0,0 +1,9 @@ +-- supporting testfile; belongs to 'cl_spec.lua' + +describe('Runs test with garbage collection failure', function() + it('throws error in __gc metamethod', function() + setmetatable({}, { __gc = function() error('gc error') end}) + collectgarbage() + collectgarbage() + end) +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 9cd888af..7fd9be28 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -427,6 +427,24 @@ describe('Tests error messages through the command line', function() local expected = 'No test files found matching Lua pattern: this_filename_does_simply_not_exist$' assert.is_equal(expected, errmsg) end) + + it('when __gc metamethod throws error', function() + local noGC = xpcall(function() + setmetatable({}, { __gc = function() error('gc error') end}) + collectgarbage() + collectgarbage() + end, function() end) + if noGC then pending('no __gc metamethod support') end + + local success, exitcode, result = executeBusted('--pattern=cl_gc_error.lua$') + local err = result:match('Error %-> (.-)\n') + local errmsg = result:match('\n([^\n]-%(spec[/\\].-%))\n') + local expected = 'error in __gc metamethod (spec/cl_gc_error.lua:5: gc error)' + assert.is_false(success) + assert.is_equal(1, exitcode) + assert.is_truthy(err) + assert.is_equal(expected, errmsg) + end) end) local has_moon = pcall(require, 'moonscript') From 4a788d824a90b78336585d0882c7c4d072d3572e Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 22 Aug 2015 22:57:50 -0700 Subject: [PATCH 236/293] Fix tests for Windows --- busted/modules/cli.lua | 2 +- spec/cl_output_handler.lua | 2 +- spec/cl_spec.lua | 4 ++-- spec/modules/cli_spec.lua | 17 +++++++++-------- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index dde8d6d3..164a04ac 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -90,7 +90,7 @@ return function(options) end local function processDir(key, value, altkey, opt) - local dpath = path.join(cliArgsParsed[key] or '', value) + local dpath = path.normpath(path.join(cliArgsParsed[key] or '', value)) processOption(key, dpath, altkey, opt) return true end diff --git a/spec/cl_output_handler.lua b/spec/cl_output_handler.lua index b0fb48f0..cd7c3ae2 100644 --- a/spec/cl_output_handler.lua +++ b/spec/cl_output_handler.lua @@ -8,7 +8,7 @@ return function(options) cli:set_name('cl_output_handler') cli:add_flag('--time', 'show timestamps') - cli:add_option('--time-format=FORMAT', 'format string according to strftime', '!%c') + cli:add_option('--time-format=FORMAT', 'format string according to strftime', '!%a %b %d %H:%M:%S %Y') local cliArgs = cli:parse(args) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 7fd9be28..a18a3365 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -443,7 +443,7 @@ describe('Tests error messages through the command line', function() assert.is_false(success) assert.is_equal(1, exitcode) assert.is_truthy(err) - assert.is_equal(expected, errmsg) + assert.is_equal(normpath(expected), errmsg) end) end) @@ -608,7 +608,7 @@ describe('Tests Xoutput commandline option', function() it('forwards single option to output handler', function() local _, _, result = executeBusted('--output=spec/cl_output_handler.lua -Xoutput "--time" --pattern=cl_success.lua$') local timestamp = result:match('^%[(.-)]') - assert.is_equal('Fri Jan 2 10:17:36 1970', timestamp) + assert.is_equal('Fri Jan 02 10:17:36 1970', timestamp) end) it('forwards multiple options to output handler', function() diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 37b0e8fe..47785b64 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -1,4 +1,5 @@ local path = require 'pl.path' +local normpath = path.normpath describe('Tests command-line interface', function() it('default options', function() @@ -213,22 +214,22 @@ describe('Tests command-line interface', function() it('specify --directory', function() local cli = require 'busted.modules.cli'() local args = cli:parse({ '--directory=/path/to/dir' }) - assert.is_equal('/path/to/dir', args.C) - assert.is_equal('/path/to/dir', args.directory) + assert.is_equal(normpath('/path/to/dir'), args.C) + assert.is_equal(normpath('/path/to/dir'), args.directory) end) it('specify --directory multiple times', function() local cli = require 'busted.modules.cli'() local args = cli:parse({ '--directory=/path/to', '-C', 'dir', '--directory=subdir' }) - assert.is_equal('/path/to/dir/subdir', args.C) - assert.is_equal('/path/to/dir/subdir', args.directory) + assert.is_equal(normpath('/path/to/dir/subdir'), args.C) + assert.is_equal(normpath('/path/to/dir/subdir'), args.directory) end) it('specify --directory multiple times with multiple roots', function() local cli = require 'busted.modules.cli'() local args = cli:parse({ '--directory=/path/to', '-C', 'dir', '--directory=/new/path' }) - assert.is_equal('/new/path', args.C) - assert.is_equal('/new/path', args.directory) + assert.is_equal(normpath('/new/path'), args.C) + assert.is_equal(normpath('/new/path'), args.directory) end) it('specify --run', function() @@ -318,8 +319,8 @@ describe('Tests using .busted tasks', function() assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) assert.is_same({'specs'}, args.ROOT) - assert.is_equal('spec/.hidden', args.C) - assert.is_equal('spec/.hidden', args.directory) + assert.is_equal(normpath('spec/.hidden'), args.C) + assert.is_equal(normpath('spec/.hidden'), args.directory) assert.is_equal('_spec', args.p) assert.is_equal('_spec%.lua$', args.pattern) assert.is_equal('os.time()', args.seed) From 6dc074131546e02732a35fee9e13c394dbb9bfda Mon Sep 17 00:00:00 2001 From: Gabriel Sobrinho Date: Sun, 20 Sep 2015 14:07:38 -0300 Subject: [PATCH 237/293] Added pt-BR language to i18n --- busted/languages/pt-BR.lua | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 busted/languages/pt-BR.lua diff --git a/busted/languages/pt-BR.lua b/busted/languages/pt-BR.lua new file mode 100644 index 00000000..06f7a154 --- /dev/null +++ b/busted/languages/pt-BR.lua @@ -0,0 +1,49 @@ +local s = require('say') + +s:set_namespace('pt-BR') + +-- 'Pending: test.lua @ 12 \n description +s:set('output.pending', 'Pendente') +s:set('output.failure', 'Falha') +s:set('output.error', 'Erro') +s:set('output.success', 'Sucesso') + +s:set('output.pending_plural', 'pendentes') +s:set('output.failure_plural', 'falhas') +s:set('output.error_plural', 'erros') +s:set('output.success_plural', 'sucessos') + +s:set('output.pending_zero', 'pendentes') +s:set('output.failure_zero', 'falhas') +s:set('output.error_zero', 'erros') +s:set('output.success_zero', 'sucessos') + +s:set('output.pending_single', 'pendente') +s:set('output.failure_single', 'falha') +s:set('output.error_single', 'erro') +s:set('output.success_single', 'sucesso') + +s:set('output.seconds', 'segundos') + +s:set('output.no_test_files_match', 'Nenhum arquivo de teste encontrado com o padrão do Lua: %s') + +-- definitions following are not used within the 'say' namespace +return { + failure_messages = { + 'Você tem %d testes quebrados', + 'Seus testes estão quebrados', + 'Seu código está mal e você deveria sentir-se mal', + 'Seu código está na zona de perigo', + 'Jogo estranho. A única forma de ganhar é não testar', + 'Minha avó escreveu testes melhores em um 386', + 'Cada vez que encontrar uma falha, beba outra cerveja', + 'Isso não está poético' + }, + success_messages = { + 'Perfeito! Todos os testes estão passando', + 'Não se preocupe, tem testes', + 'Isso está poético', + 'Excelente', + 'Os testes passaram, beba outra cerveja', + } +} From bd7669b0b95bc071dc4cb15fc36c42e056bd3c93 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 20 Sep 2015 16:39:18 -0700 Subject: [PATCH 238/293] Refactor output handler loader --- busted/modules/configuration_loader.lua | 4 +- busted/modules/output_handler_loader.lua | 10 +++-- busted/runner.lua | 55 +++++++++--------------- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index fbefd9a1..0887027d 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -1,6 +1,6 @@ -return function() - local tablex = require 'pl.tablex' +local tablex = require 'pl.tablex' +return function() -- Function to load the .busted configuration file if available local loadBustedConfigurationFile = function(configFile, config, defaults) if type(configFile) ~= 'table' then diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index 14ab9299..41c45d4e 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -2,7 +2,7 @@ local path = require 'pl.path' local hasMoon, moonscript = pcall(require, 'moonscript') return function() - local loadOutputHandler = function(busted, output, options, defaultOutput) + local loadOutputHandler = function(busted, output, options) local handler local success, err = pcall(function() @@ -21,10 +21,14 @@ return function() if not success then busted.publish({ 'error', 'output' }, { descriptor = 'output', name = output }, nil, err, {}) - handler = require('busted.outputHandlers.' .. defaultOutput) + handler = require('busted.outputHandlers.' .. options.defaultOutput) end - return handler(options) + if options.enableSound then + require 'busted.outputHandlers.sound'(options) + end + + handler(options):subscribe(options) end return loadOutputHandler diff --git a/busted/runner.lua b/busted/runner.lua index f3b5e0fb..d4e983e5 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -107,65 +107,52 @@ return function(options) return nil, true end) + -- Set up randomization options + busted.sort = cliArgs['sort-tests'] + busted.randomize = cliArgs['shuffle-tests'] + busted.randomseed = tonumber(cliArgs.seed) or os.time() + -- Set up output handler to listen to events - local outputHandlerOptions = { + outputHandlerLoader(busted, cliArgs.output, { + defaultOutput = options.defaultOutput, + enableSound = cliArgs['enable-sound'], verbose = cliArgs.verbose, suppressPending = cliArgs['suppress-pending'], language = cliArgs.lang, deferPrint = cliArgs['defer-print'], - arguments = cliArgs.Xoutput - } - - local outputHandler = outputHandlerLoader(busted, cliArgs.output, outputHandlerOptions, options.defaultOutput) - outputHandler:subscribe(outputHandlerOptions) - - if cliArgs['enable-sound'] then - require 'busted.outputHandlers.sound'(outputHandlerOptions) - end - - -- Set up randomization options - busted.sort = cliArgs['sort-tests'] - busted.randomize = cliArgs['shuffle-tests'] - busted.randomseed = tonumber(cliArgs.seed) or os.time() + arguments = cliArgs.Xoutput, + }) - -- Set up tag and test filter options - local filterLoaderOptions = { + -- Load tag and test filters + filterLoader(busted, { tags = cliArgs.tags, excludeTags = cliArgs['exclude-tags'], filter = cliArgs.filter, filterOut = cliArgs['filter-out'], list = cliArgs.list, nokeepgoing = not cliArgs['keep-going'], - } - - -- Load tag and test filters - filterLoader(busted, filterLoaderOptions) + }) -- Set up helper script if cliArgs.helper and cliArgs.helper ~= '' then - local helperOptions = { + helperLoader(busted, cliArgs.helper, { verbose = cliArgs.verbose, language = cliArgs.lang, arguments = cliArgs.Xhelper - } - - helperLoader(busted, cliArgs.helper, helperOptions) + }) end - -- Set up test loader options - local testFileLoaderOptions = { + -- Load test directory + local rootFiles = cliArgs.ROOT or { fileName } + local pattern = cliArgs.pattern + local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) + testFileLoader(rootFiles, pattern, { verbose = cliArgs.verbose, sort = cliArgs['sort-files'], shuffle = cliArgs['shuffle-files'], recursive = cliArgs['recursive'], seed = busted.randomseed - } - - -- Load test directory - local rootFiles = cliArgs.ROOT or { fileName } - local pattern = cliArgs.pattern - local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) - testFileLoader(rootFiles, pattern, testFileLoaderOptions) + }) -- If running standalone, setup test file to be compatible with live coding if options.standalone then From 94c8307278fb61f86aac249f10c11a86763543f7 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 3 Oct 2015 13:52:44 -0700 Subject: [PATCH 239/293] Fix unintentional stack trace on exit This fixes the stack trace on exiting with an error code on Lua 5.3. On Lua 5.3, `error()` is not silent, so don't throw an `error()` to exit with error for Lua > 5.2. For Lua versions 5.1 and 5.2 continue to throw a silent `error()` to allow the Lua state to be closed naturally whenever possible. --- busted/compatibility.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index f80b0dc4..403788bb 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -33,7 +33,11 @@ return { unpack = table.unpack or unpack, exit = function(code) - if code ~= 0 then error() end + if code ~= 0 and _VERSION:match('^Lua 5%.[12]$') then + error() + elseif code ~= 0 then + code = 1 + end if _VERSION == 'Lua 5.1' and (type(jit) ~= 'table' or not jit.version or jit.version_num < 20000) then -- From Lua 5.1 manual: @@ -57,6 +61,6 @@ return { end end end - os.exit(0, true) + os.exit(code, true) end, } From a36563c37384f7a2c163ac83c67f90e76842e81e Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 25 Oct 2015 09:42:20 -0700 Subject: [PATCH 240/293] Update lua_cliargs dependency --- busted-2.0.rc10-0.rockspec | 2 +- busted-scm-0.rockspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/busted-2.0.rc10-0.rockspec b/busted-2.0.rc10-0.rockspec index 28f7f206..7de6114e 100644 --- a/busted-2.0.rc10-0.rockspec +++ b/busted-2.0.rc10-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.5-0', + 'lua_cliargs >= 2.5-0, < 3.0', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index bfcdbef0..0c5cff25 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.5-0', + 'lua_cliargs >= 2.5-0, < 3.0', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', From 4ac29e5514dc7aff11d0afb5066ae767b1dda1f3 Mon Sep 17 00:00:00 2001 From: Jack Lawson Date: Mon, 26 Oct 2015 09:00:42 -0700 Subject: [PATCH 241/293] Version bump to 2.0rc10-1 --- busted-2.0.rc10-0.rockspec => busted-2.0.rc10-1.rockspec | 6 +++--- busted/core.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename busted-2.0.rc10-0.rockspec => busted-2.0.rc10-1.rockspec (98%) diff --git a/busted-2.0.rc10-0.rockspec b/busted-2.0.rc10-1.rockspec similarity index 98% rename from busted-2.0.rc10-0.rockspec rename to busted-2.0.rc10-1.rockspec index 7de6114e..fafdf835 100644 --- a/busted-2.0.rc10-0.rockspec +++ b/busted-2.0.rc10-1.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc10-0' +version = '2.0.rc10-1' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc10-0.tar.gz', - dir = 'busted-2.0.rc10-0' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc10-1.tar.gz', + dir = 'busted-2.0.rc10-1' } description = { summary = 'Elegant Lua unit testing.', diff --git a/busted/core.lua b/busted/core.lua index b68037d2..f66430eb 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -44,7 +44,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc10-0' + busted.version = '2.0.rc10-1' local root = require 'busted.context'() busted.context = root.ref() From 3cfe9bf91daf4c6f5ba46a1bf82557eab07e534f Mon Sep 17 00:00:00 2001 From: Ryan Hartlage Date: Tue, 27 Oct 2015 13:21:12 -0400 Subject: [PATCH 242/293] Ensure that pre-release versions of lua_cliargs 3 aren't used as a dependency --- busted-2.0.rc10-1.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted-2.0.rc10-1.rockspec b/busted-2.0.rc10-1.rockspec index fafdf835..f92f0f04 100644 --- a/busted-2.0.rc10-1.rockspec +++ b/busted-2.0.rc10-1.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.5-0, < 3.0', + 'lua_cliargs >= 2.5-0, < 3.0.rc-1', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', From 7649118be74e769b8eb71270fa4ffcdcade8962c Mon Sep 17 00:00:00 2001 From: Ryan Hartlage Date: Tue, 27 Oct 2015 16:11:17 -0400 Subject: [PATCH 243/293] Update busted-scm-0.rockspec --- busted-scm-0.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 0c5cff25..f9e29095 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.5-0, < 3.0', + 'lua_cliargs >= 2.5-0, < 3.0.rc-1', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', From 9eb6c9cf93bc558a2398c822b896990e48bd69fd Mon Sep 17 00:00:00 2001 From: Robert Ditthardt Date: Mon, 26 Oct 2015 19:27:33 -0700 Subject: [PATCH 244/293] Implement option to choose the lua interpreter --- busted/compatibility.lua | 2 ++ busted/modules/cli.lua | 13 +++++++++++++ spec/cl_spec.lua | 6 ++++++ spec/lua.lua | 4 ++++ 4 files changed, 25 insertions(+) create mode 100755 spec/lua.lua diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 403788bb..2fcbb4b8 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -63,4 +63,6 @@ return { end os.exit(code, true) end, + + execute = require 'pl.utils'.execute, } diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 164a04ac..452ca17e 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -1,6 +1,8 @@ local utils = require 'busted.utils' local path = require 'pl.path' local tablex = require 'pl.tablex' +local exit = require 'busted.compatibility'.exit +local execute = require 'busted.compatibility'.execute return function(options) local appName = '' @@ -129,6 +131,7 @@ return function(options) cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processLoaders) cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) + cli:add_option('--lua=LUA', 'The path to the lua interpreter busted should run under', nil, processOption) cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) @@ -137,6 +140,7 @@ return function(options) cli:add_flag('-v, --[no-]verbose', 'verbose output of errors', false, processOption) cli:add_flag('-s, --[no-]enable-sound', 'executes `say` command if available', false, processOption) cli:add_flag('-l, --list', 'list the names of all tests instead of running them', false, processOption) + cli:add_flag('--ignore-lua', 'Whether or not to ignore the lua directive', false, processOption) cli:add_flag('--[no-]lazy', 'use lazy setup/teardown as the default', false, processOption) cli:add_flag('--[no-]auto-insulate', 'enable file insulation', true, processOption) cli:add_flag('-k, --[no-]keep-going', 'continue as much as possible after an error or failure', true, processOption) @@ -172,6 +176,15 @@ return function(options) cliArgs = tablex.merge(cliArgs, cliArgsParsed, true) end + -- Switch lua, we should rebuild this feature once luarocks changes how it + -- handles executeable lua files. + if cliArgs['lua'] and not cliArgs['ignore-lua'] then + local _, code = execute( + cliArgs['lua']..' '..args[0]..' --ignore-lua '..table.concat(args, ' ') + ) + exit(code) + end + -- Fixup options in case options from config file are not of the right form cliArgs.tags = fixupList(cliArgs.tags) cliArgs.t = cliArgs.tags diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index a18a3365..629024e1 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -212,6 +212,12 @@ describe('Tests the busted command-line options', function() assert.is_equal(1, exitcode) end) + it('can switch interpreters', function() + local success, exitcode, out = executeBusted('--lua=spec/lua.lua spec/cl_success.lua') + assert.is_true(success) + assert.is_equal(0, exitcode) + assert.equal('bin/busted --ignore-lua --lua=spec/lua.lua spec/cl_success.lua\n', out) + end) end) describe('Tests failing tests through the commandline', function() diff --git a/spec/lua.lua b/spec/lua.lua new file mode 100755 index 00000000..61e40e50 --- /dev/null +++ b/spec/lua.lua @@ -0,0 +1,4 @@ +#!/usr/bin/env lua +local exit = require 'busted.compatibility'.exit +print(table.concat(arg, ' ')) +exit(0) From 2c68aca329d877ec84f26815dd56211b11c728cd Mon Sep 17 00:00:00 2001 From: Robert Ditthardt Date: Tue, 27 Oct 2015 13:50:55 -0700 Subject: [PATCH 245/293] Release --- busted-2.0.rc10-1.rockspec => busted-2.0.rc11-0.rockspec | 6 +++--- busted/core.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename busted-2.0.rc10-1.rockspec => busted-2.0.rc11-0.rockspec (98%) diff --git a/busted-2.0.rc10-1.rockspec b/busted-2.0.rc11-0.rockspec similarity index 98% rename from busted-2.0.rc10-1.rockspec rename to busted-2.0.rc11-0.rockspec index f92f0f04..46fb25d6 100644 --- a/busted-2.0.rc10-1.rockspec +++ b/busted-2.0.rc11-0.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc10-1' +version = '2.0.rc11-0' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc10-1.tar.gz', - dir = 'busted-2.0.rc10-1' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc11-0.tar.gz', + dir = 'busted-2.0.rc11-0' } description = { summary = 'Elegant Lua unit testing.', diff --git a/busted/core.lua b/busted/core.lua index f66430eb..5e55e016 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -44,7 +44,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc10-1' + busted.version = '2.0.rc11-0' local root = require 'busted.context'() busted.context = root.ref() From 4e13e5917aa5735122f81eab3be1f256f8ab6135 Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Fri, 20 Nov 2015 01:58:46 +0000 Subject: [PATCH 246/293] Add Gitter badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 43a2ff0e..232978e6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Busted ====== +[![Join the chat at https://gitter.im/Olivine-Labs/busted](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Olivine-Labs/busted?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + [![travis-ci status](https://secure.travis-ci.org/Olivine-Labs/busted.png)](http://travis-ci.org/#!/Olivine-Labs/busted/builds) busted is a unit testing framework with a focus on being **easy to From 02f26cd70b3d8bd7c8cc0092c8da0d9d0a5a0a9d Mon Sep 17 00:00:00 2001 From: Ahmad Amireh Date: Sat, 24 Oct 2015 17:44:09 +0300 Subject: [PATCH 247/293] Upgrade to lua_cliargs 3.0-0 This patch apples the necessary changes to use the 3.0 version of lua_cliargs. --- busted-2.0.rc11-0.rockspec | 2 +- busted/modules/cli.lua | 91 ++++++++++++++++++++------------------ spec/cl_helper_script.lua | 8 ++-- spec/cl_output_handler.lua | 4 +- 4 files changed, 55 insertions(+), 50 deletions(-) diff --git a/busted-2.0.rc11-0.rockspec b/busted-2.0.rc11-0.rockspec index 46fb25d6..7989cdeb 100644 --- a/busted-2.0.rc11-0.rockspec +++ b/busted-2.0.rc11-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.5-0, < 3.0.rc-1', + 'lua_cliargs = 3.0-0', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 452ca17e..2e6cca57 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -7,7 +7,7 @@ local execute = require 'busted.compatibility'.execute return function(options) local appName = '' local options = options or {} - local cli = require 'cliargs' + local cli = require 'cliargs.core'() local configLoader = require 'busted.modules.configuration_loader'() @@ -108,57 +108,57 @@ return function(options) end -- Load up the command-line interface options - cli:add_flag('--version', 'prints the program version and exits', false, processOption) + cli:flag('--version', 'prints the program version and exits', false, processOption) if not options.standalone then - cli:optarg('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 999, processArgList) + cli:splat('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 999, processArgList) - cli:add_option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) + cli:option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) end - cli:add_option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) - cli:add_option('-C, --directory=DIR', 'change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) - cli:add_option('-f, --config-file=FILE', 'load configuration options from FILE', nil, processOptions) - cli:add_option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) - cli:add_option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) - cli:add_option('--filter=PATTERN', 'only run test names matching the Lua pattern', {}, processMultiOption) - cli:add_option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', {}, processMultiOption) - cli:add_option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processPath) - cli:add_option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processPath) - cli:add_option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) - cli:add_option('--repeat=COUNT', 'run the tests repeatedly', '1', processNumber) - cli:add_option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processNumber) - cli:add_option('--lang=LANG', 'language for error messages', 'en', processOption) - cli:add_option('--loaders=NAME', 'test file loaders', defaultLoaders, processLoaders) - cli:add_option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) - cli:add_option('--lua=LUA', 'The path to the lua interpreter busted should run under', nil, processOption) - - cli:add_option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) - cli:add_option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) - - cli:add_flag('-c, --[no-]coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', false, processOption) - cli:add_flag('-v, --[no-]verbose', 'verbose output of errors', false, processOption) - cli:add_flag('-s, --[no-]enable-sound', 'executes `say` command if available', false, processOption) - cli:add_flag('-l, --list', 'list the names of all tests instead of running them', false, processOption) - cli:add_flag('--ignore-lua', 'Whether or not to ignore the lua directive', false, processOption) - cli:add_flag('--[no-]lazy', 'use lazy setup/teardown as the default', false, processOption) - cli:add_flag('--[no-]auto-insulate', 'enable file insulation', true, processOption) - cli:add_flag('-k, --[no-]keep-going', 'continue as much as possible after an error or failure', true, processOption) - cli:add_flag('-R, --[no-]recursive', 'recurse into subdirectories', true, processOption) - cli:add_flag('--[no-]shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processShuffle) - cli:add_flag('--[no-]shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) - cli:add_flag('--[no-]shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) - cli:add_flag('--[no-]sort', 'sort file and test order (--sort-tests and --sort-files)', processSort) - cli:add_flag('--[no-]sort-files', 'sort file execution order', processOption) - cli:add_flag('--[no-]sort-tests', 'sort test order within a file', processOption) - cli:add_flag('--[no-]suppress-pending', 'suppress `pending` test output', false, processOption) - cli:add_flag('--[no-]defer-print', 'defer print to when test suite is complete', false, processOption) + cli:option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) + cli:option('-C, --directory=DIR', 'change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) + cli:option('-f, --config-file=FILE', 'load configuration options from FILE', nil, processOptions) + cli:option('-t, --tags=TAGS', 'only run tests with these #tags', {}, processList) + cli:option('--exclude-tags=TAGS', 'do not run tests with these #tags, takes precedence over --tags', {}, processList) + cli:option('--filter=PATTERN', 'only run test names matching the Lua pattern', {}, processMultiOption) + cli:option('--filter-out=PATTERN', 'do not run test names matching the Lua pattern, takes precedence over --filter', {}, processMultiOption) + cli:option('-m, --lpath=PATH', 'optional path to be prefixed to the Lua module search path', lpathprefix, processPath) + cli:option('--cpath=PATH', 'optional path to be prefixed to the Lua C module search path', cpathprefix, processPath) + cli:option('-r, --run=RUN', 'config to run from .busted file', nil, processOption) + cli:option('--repeat=COUNT', 'run the tests repeatedly', '1', processNumber) + cli:option('--seed=SEED', 'random seed value to use for shuffling test order', defaultSeed, processNumber) + cli:option('--lang=LANG', 'language for error messages', 'en', processOption) + cli:option('--loaders=NAME', 'test file loaders', defaultLoaders, processLoaders) + cli:option('--helper=PATH', 'A helper script that is run before tests', nil, processOption) + cli:option('--lua=LUA', 'The path to the lua interpreter busted should run under', nil, processOption) + + cli:option('-Xoutput OPTION', 'pass `OPTION` as an option to the output handler. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) + cli:option('-Xhelper OPTION', 'pass `OPTION` as an option to the helper script. If `OPTION` contains commas, it is split into multiple options at the commas.', {}, processList) + + cli:flag('-c, --[no-]coverage', 'do code coverage analysis (requires `LuaCov` to be installed)', false, processOption) + cli:flag('-v, --[no-]verbose', 'verbose output of errors', false, processOption) + cli:flag('-s, --[no-]enable-sound', 'executes `say` command if available', false, processOption) + cli:flag('-l, --list', 'list the names of all tests instead of running them', false, processOption) + cli:flag('--ignore-lua', 'Whether or not to ignore the lua directive', false, processOption) + cli:flag('--[no-]lazy', 'use lazy setup/teardown as the default', false, processOption) + cli:flag('--[no-]auto-insulate', 'enable file insulation', true, processOption) + cli:flag('-k, --[no-]keep-going', 'continue as much as possible after an error or failure', true, processOption) + cli:flag('-R, --[no-]recursive', 'recurse into subdirectories', true, processOption) + cli:flag('--[no-]shuffle', 'randomize file and test order, takes precedence over --sort (--shuffle-test and --shuffle-files)', processShuffle) + cli:flag('--[no-]shuffle-files', 'randomize file execution order, takes precedence over --sort-files', processOption) + cli:flag('--[no-]shuffle-tests', 'randomize test order within a file, takes precedence over --sort-tests', processOption) + cli:flag('--[no-]sort', 'sort file and test order (--sort-tests and --sort-files)', processSort) + cli:flag('--[no-]sort-files', 'sort file execution order', processOption) + cli:flag('--[no-]sort-tests', 'sort test order within a file', processOption) + cli:flag('--[no-]suppress-pending', 'suppress `pending` test output', false, processOption) + cli:flag('--[no-]defer-print', 'defer print to when test suite is complete', false, processOption) local function parse(args) -- Parse the cli arguments - local cliArgs, cliErr = cli:parse(args, true) + local cliArgs, cliErr = cli:parse(args) if not cliArgs then - return nil, cliErr + return nil, appName .. ': error: ' .. cliErr .. '; re-run with --help for usage.' end -- Load busted config file if available @@ -216,6 +216,11 @@ return function(options) return cli:set_name(name) end, + set_silent = function(self, name) + appName = name + return cli:set_silent(name) + end, + parse = function(self, args) return parse(args) end diff --git a/spec/cl_helper_script.lua b/spec/cl_helper_script.lua index c8db6f87..19967830 100644 --- a/spec/cl_helper_script.lua +++ b/spec/cl_helper_script.lua @@ -8,10 +8,10 @@ local assert = require 'busted'.assert local cli = require 'cliargs' cli:set_name('cl_helper_script') -cli:add_flag('--fail-setup', 'force setup to fail') -cli:add_flag('--fail-teardown', 'force teardown to fail') -cli:add_flag('--fail-before-each', 'force before each to fail') -cli:add_flag('--fail-after-each', 'force after each to fail') +cli:flag('--fail-setup', 'force setup to fail') +cli:flag('--fail-teardown', 'force teardown to fail') +cli:flag('--fail-before-each', 'force before each to fail') +cli:flag('--fail-after-each', 'force after each to fail') local cliArgs = cli:parse(arg) diff --git a/spec/cl_output_handler.lua b/spec/cl_output_handler.lua index cd7c3ae2..8a253a4a 100644 --- a/spec/cl_output_handler.lua +++ b/spec/cl_output_handler.lua @@ -7,8 +7,8 @@ return function(options) local args = options.arguments cli:set_name('cl_output_handler') - cli:add_flag('--time', 'show timestamps') - cli:add_option('--time-format=FORMAT', 'format string according to strftime', '!%a %b %d %H:%M:%S %Y') + cli:flag('--time', 'show timestamps') + cli:option('--time-format=FORMAT', 'format string according to strftime', '!%a %b %d %H:%M:%S %Y') local cliArgs = cli:parse(args) From 3b44b4587af57def94b85eb26bebb088de39f54a Mon Sep 17 00:00:00 2001 From: Ahmad Amireh Date: Tue, 12 Jan 2016 11:33:01 +0200 Subject: [PATCH 248/293] Upgrade to lua_cliargs-3.0-1 --- busted-2.0.rc11-0.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted-2.0.rc11-0.rockspec b/busted-2.0.rc11-0.rockspec index 7989cdeb..4f0cc947 100644 --- a/busted-2.0.rc11-0.rockspec +++ b/busted-2.0.rc11-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs = 3.0-0', + 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', From 159c5196adbad73115d37741ceb4e3da3004d4e5 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 14 Jan 2016 23:23:44 -0800 Subject: [PATCH 249/293] Fix scm-rockspec with correct lua_cliargs version This fixes the scm rockspec to use correct version of lua_cliargs. --- busted-scm-0.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index f9e29095..dae42c94 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -19,7 +19,7 @@ description = { } dependencies = { 'lua >= 5.1', - 'lua_cliargs >= 2.5-0, < 3.0.rc-1', + 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', 'dkjson >= 2.1.0', 'say >= 1.3-0', From 1b52da32518f6358be8e1829e0a2141526efc72d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 11 Jan 2016 02:37:55 -0800 Subject: [PATCH 250/293] Refactor copying of context in base output handler This allows for adding new keys to a test context without the need to change the output handlers in order to copy a new or changed key. We can't just copy the entire table, otherwise the json output handler will break. The `env` key and any values that evaluate to functions cannot be copied. --- busted/outputHandlers/base.lua | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 6690b611..287371f2 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -53,19 +53,25 @@ return function() end handler.format = function(element, parent, message, debug, isError) + local function copyElement(e) + local copy = {} + for k,v in next, e do + if type(v) ~= 'function' and k ~= 'env' then + copy[k] = v + end + end + return copy + end + local formatted = { trace = debug or element.trace, - element = { - name = element.name, - descriptor = element.descriptor, - attributes = element.attributes, - trace = element.trace or debug, - }, + element = copyElement(element), name = handler.getFullName(element), message = message, randomseed = parent and parent.randomseed, isError = isError } + formatted.element.trace = element.trace or debug return formatted end From 7989876058543a5233cc7c0e9cdf6483c1d0c8e5 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 11 Jan 2016 02:36:32 -0800 Subject: [PATCH 251/293] Remove unused variable from utils --- busted/utils.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/busted/utils.lua b/busted/utils.lua index a8d359c4..b682532f 100644 --- a/busted/utils.lua +++ b/busted/utils.lua @@ -1,5 +1,3 @@ -local path = require 'pl.path' - math.randomseed(os.time()) return { From 9b4160f652a4bd95183e1cf55af44e79f979c3eb Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 11 Jan 2016 02:49:19 -0800 Subject: [PATCH 252/293] Add `match` to busted env and exported functions This adds the `match` function from `luassert` to the busted test environment and exports it as part of the busted public API. --- busted/init.lua | 2 ++ spec/core_spec.lua | 1 + spec/export_spec.lua | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/busted/init.lua b/busted/init.lua index 64cedfc1..3094a2a9 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -89,11 +89,13 @@ local function init(busted) local spy = require 'luassert.spy' local mock = require 'luassert.mock' local stub = require 'luassert.stub' + local match = require 'luassert.match' busted.export('assert', assert) busted.export('spy', spy) busted.export('mock', mock) busted.export('stub', stub) + busted.export('match', match) busted.exportApi('publish', busted.publish) busted.exportApi('subscribe', busted.subscribe) diff --git a/spec/core_spec.lua b/spec/core_spec.lua index ba0c07a5..a7267408 100644 --- a/spec/core_spec.lua +++ b/spec/core_spec.lua @@ -10,6 +10,7 @@ assert(type(after_each) == 'function') assert(type(spy) == 'table') assert(type(stub) == 'table') assert(type(mock) == 'table') +assert(type(match) == 'table') assert(type(assert) == 'table') describe('Before each', function() diff --git a/spec/export_spec.lua b/spec/export_spec.lua index b0ce3ab1..24b782be 100644 --- a/spec/export_spec.lua +++ b/spec/export_spec.lua @@ -50,11 +50,12 @@ describe('tests require "busted"', function() assert.is_equal(after_each, require 'busted'.after_each) end) - it('exports assert and mocks', function() + it('exports assert, mocks, and matchers', function() assert.is_equal(assert, require 'busted'.assert) assert.is_equal(spy, require 'busted'.spy) assert.is_equal(mock, require 'busted'.mock) assert.is_equal(stub, require 'busted'.stub) + assert.is_equal(match, require 'busted'.match) end) it('exports publish/subscribe', function() From 5dbe16f5d5f8951480a878ffd15e168f5db5cf32 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 11 Jan 2016 03:08:18 -0800 Subject: [PATCH 253/293] Fix for allowing `strict` usage in a test file This updates the test setup code to be compatible with `strict`. --- busted/block.lua | 13 +++++++------ busted/core.lua | 9 ++++++--- busted/init.lua | 4 +++- spec/cl_spec.lua | 7 +++++++ spec/strict.lua | 39 +++++++++++++++++++++++++++++++++++++++ spec/strict_spec.lua | 9 +++++++++ 6 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 spec/strict.lua create mode 100644 spec/strict_spec.lua diff --git a/busted/block.lua b/busted/block.lua index 52e789a5..49e50c44 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -14,20 +14,21 @@ end return function(busted) local block = {} + local root = busted.context.get() function block.reject(descriptor, element) - local env = getfenv(element.run) - if env[descriptor] then - element.env[descriptor] = function(...) - error("'" .. descriptor .. "' not supported inside current context block", 2) - end + element.env[descriptor] = function(...) + error("'" .. descriptor .. "' not supported inside current context block", 2) end end function block.rejectAll(element) + local env = getfenv(element.run) block.reject('randomize', element) for descriptor, _ in pairs(busted.executors) do - block.reject(descriptor, element) + if root.env[descriptor] and (env ~= _G and env[descriptor] or rawget(env, descriptor)) then + block.reject(descriptor, element) + end end end diff --git a/busted/core.lua b/busted/core.lua index 5e55e016..6600a972 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -204,6 +204,11 @@ return function() environment.set(key, value) end + function busted.hide(key, value) + busted.api[key] = nil + environment.set(key, nil) + end + function busted.register(descriptor, executor, attributes) local alias = nil if type(executor) == 'string' then @@ -244,9 +249,7 @@ return function() local edescriptor = alias or descriptor busted.executors[edescriptor] = publisher - if descriptor ~= 'file' then - busted.export(edescriptor, publisher) - end + busted.export(edescriptor, publisher) busted.subscribe({ 'register', descriptor }, function(name, fn, trace, attributes) local ctx = busted.context.get() diff --git a/busted/init.lua b/busted/init.lua index 64cedfc1..78332789 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -30,7 +30,7 @@ local function init(busted) block.rejectAll(element) element.env.finally = function(fn) finally = fn end - element.env.pending = function(msg) busted.pending(msg) end + element.env.pending = busted.pending local pass, ancestor = block.execAll('before_each', parent, true) @@ -85,6 +85,8 @@ local function init(busted) busted.register('spec', 'it') busted.register('test', 'it') + busted.hide('file') + local assert = require 'luassert' local spy = require 'luassert.spy' local mock = require 'luassert.mock' diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 629024e1..c2856173 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -680,3 +680,10 @@ describe('Tests helper script', function() assert.is_equal(4, exitcode) end) end) + +describe('Tests strict with helper script', function() + it('does not detect any errors', function() + local success = executeBusted('--helper=spec/cl_helper_script.lua --pattern=strict_spec.lua$') + assert.is_true(success) + end) +end) diff --git a/spec/strict.lua b/spec/strict.lua new file mode 100644 index 00000000..03660f28 --- /dev/null +++ b/spec/strict.lua @@ -0,0 +1,39 @@ +-- strict.lua +-- checks uses of undeclared global variables +-- All global variables must be 'declared' through a regular assignment +-- (even assigning nil will do) in a main chunk before being used +-- anywhere or assigned to inside a function. +-- distributed under the Lua license: http://www.lua.org/license.html + +local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget + +local mt = getmetatable(_G) +if mt == nil then + mt = {} + setmetatable(_G, mt) +end + +mt.__declared = {} + +local function what () + local d = getinfo(3, "S") + return d and d.what or "C" +end + +mt.__newindex = function (t, n, v) + if not mt.__declared[n] then + local w = what() + if w ~= "main" and w ~= "C" then + error("assign to undeclared variable '"..n.."'", 2) + end + mt.__declared[n] = true + end + rawset(t, n, v) +end + +mt.__index = function (t, n) + if not mt.__declared[n] and what() ~= "C" then + error("variable '"..n.."' is not declared", 2) + end + return rawget(t, n) +end diff --git a/spec/strict_spec.lua b/spec/strict_spec.lua new file mode 100644 index 00000000..e91dbce0 --- /dev/null +++ b/spec/strict_spec.lua @@ -0,0 +1,9 @@ +require 'spec.strict' + +describe('runs a single successful test with strict', function() + + it('is a succesful test with strict', function() + -- nothing here, makes it succeed + end) + +end) From a2a3be1c7e18669c7360177e1d3bcb0687596099 Mon Sep 17 00:00:00 2001 From: James Harris Date: Thu, 28 Jan 2016 11:28:41 -0600 Subject: [PATCH 254/293] Allow junit output handler to save output to file When trying to hook busted's junit output module up to an internal automated test system it is very challenging to determine what output was written to stdout by tests, and what output was written to stdout by tests and what output is part of the test summary in xml. The simplest way to handle this is to allow junit to accept an argument naming a file where the xml output should be written via the -Xoutput mechanism. This patch adds this change to junit. Change-Id: Iea996783ed62cf707f28557dc9e1ee4055e44642 --- busted/outputHandlers/junit.lua | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 348c3112..8efcc26e 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -17,6 +17,11 @@ return function(options) local stack = {} local testcase_node local testStartTime + local output_file_name + if 'table' == type(options.arguments) then + --the first argument should be the name of the xml file. + output_file_name = options.arguments[1] + end handler.suiteStart = function(suite, count, total) local suite = { @@ -56,8 +61,18 @@ return function(options) handler.exit = function() top.xml_doc.attr.time = elapsed(top.start_time) - print(xml.tostring(top.xml_doc, '', '\t', nil, false)) - + local output_string = xml.tostring(top.xml_doc, '', '\t', nil, false) + local file + if 'string' == type(output_file_name) then + file = io.open(output_file_name, 'w+b' ) + end + if file then + file:write(output_string) + file:write('\n') + file:close() + else + print(output_string) + end return nil, true end From d7ecf8170c0bce2894adacc860cf3cb47b89cb92 Mon Sep 17 00:00:00 2001 From: Chris Tallman Date: Tue, 2 Feb 2016 09:32:49 -0800 Subject: [PATCH 255/293] Fix to junit timestamp string format: Changed %T to %H:%M:%S --- busted/outputHandlers/junit.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 348c3112..96f54a35 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -27,7 +27,7 @@ return function(options) errors = 0, failures = 0, skip = 0, - timestamp = os.date('!%Y-%m-%dT%T'), + timestamp = os.date('!%Y-%m-%dT%H:%M:%S'), }) } top.xml_doc:add_direct_child(suite.xml_doc) From 7d949628d3b53d3b83ee46cd0493805242d304dc Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 17 Jan 2016 22:37:51 -0800 Subject: [PATCH 256/293] Remove dependency on luasocket This removes the dependency on luasocket by using luasystem for `gettime`, instead of using `socket.gettime`. --- .luacov | 1 - busted-2.0.rc11-0.rockspec | 3 ++- busted-scm-0.rockspec | 3 ++- busted/core.lua | 3 +++ busted/outputHandlers/base.lua | 6 ++---- busted/outputHandlers/gtest.lua | 13 ++++++------- busted/outputHandlers/junit.lua | 9 ++++----- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.luacov b/.luacov index f9b75eb0..e2605fe8 100644 --- a/.luacov +++ b/.luacov @@ -46,7 +46,6 @@ return { 'coxpcall$', 'mediator$', 'moonscript.*$', - 'socket$', }, diff --git a/busted-2.0.rc11-0.rockspec b/busted-2.0.rc11-0.rockspec index 4f0cc947..c66031a7 100644 --- a/busted-2.0.rc11-0.rockspec +++ b/busted-2.0.rc11-0.rockspec @@ -21,14 +21,15 @@ dependencies = { 'lua >= 5.1', 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', + 'luasystem >= 0.1.0-0', 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.8-0', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1.1-0', - 'luasocket >= 2.0.1' } + build = { type = 'builtin', modules = { diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index dae42c94..5a5d95b3 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -21,14 +21,15 @@ dependencies = { 'lua >= 5.1', 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', + 'luasystem >= 0.1.0-0', 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.8-0', 'lua-term >= 0.1-1', 'penlight >= 1.3.2-2', 'mediator_lua >= 1.1.1-0', - 'luasocket >= 2.0.1' } + build = { type = 'builtin', modules = { diff --git a/busted/core.lua b/busted/core.lua index 6600a972..c13426a0 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -3,6 +3,7 @@ local setfenv = require 'busted.compatibility'.setfenv local unpack = require 'busted.compatibility'.unpack local path = require 'pl.path' local pretty = require 'pl.pretty' +local system = require 'system' local throw = error local failureMt = { @@ -56,6 +57,8 @@ return function() local executors = {} local eattributes = {} + busted.gettime = system.gettime + busted.sleep = system.sleep busted.status = require 'busted.status' function busted.getTrace(element, level, msg) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 287371f2..3b0a1ca3 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -1,5 +1,3 @@ -local socket = require 'socket' - return function() local busted = require 'busted' local handler = { @@ -85,7 +83,7 @@ return function() end handler.baseSuiteStart = function() - handler.startTime = socket.gettime() + handler.startTime = busted.gettime() return nil, true end @@ -104,7 +102,7 @@ return function() end handler.baseSuiteEnd = function() - handler.endTime = socket.gettime() + handler.endTime = busted.gettime() return nil, true end diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index bc6f881d..ce003dae 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -1,5 +1,4 @@ local s = require 'say' -local socket = require 'socket' local pretty = require 'pl.pretty' local term = require 'term' @@ -172,7 +171,7 @@ return function(options) end handler.suiteStart = function(suite, count, total, randomseed) - suiteStartTime = socket.gettime() + suiteStartTime = busted.gettime() if total > 1 then io.write(repeatSuiteString:format(count, total)) end @@ -187,7 +186,7 @@ return function(options) end handler.suiteEnd = function(suite, count, total) - local elapsedTime_ms = (socket.gettime() - suiteStartTime) * 1000 + local elapsedTime_ms = (busted.gettime() - suiteStartTime) * 1000 local tests = (testCount == 1 and 'test' or 'tests') local files = (fileCount == 1 and 'file' or 'files') io.write(globalTeardown) @@ -199,7 +198,7 @@ return function(options) end handler.fileStart = function(file) - fileStartTime = socket.gettime() + fileStartTime = busted.gettime() fileTestCount = 0 io.write(fileStartString:format(file.name)) io.flush() @@ -207,7 +206,7 @@ return function(options) end handler.fileEnd = function(file) - local elapsedTime_ms = (socket.gettime() - fileStartTime) * 1000 + local elapsedTime_ms = (busted.gettime() - fileStartTime) * 1000 local tests = (fileTestCount == 1 and 'test' or 'tests') fileCount = fileCount + 1 io.write(fileEndString:format(fileTestCount, tests, file.name, elapsedTime_ms)) @@ -216,7 +215,7 @@ return function(options) end handler.testStart = function(element, parent) - testStartTime = socket.gettime() + testStartTime = busted.gettime() io.write(runString:format(getFullName(element))) io.flush() @@ -224,7 +223,7 @@ return function(options) end handler.testEnd = function(element, parent, status, debug) - local elapsedTime_ms = (socket.gettime() - testStartTime) * 1000 + local elapsedTime_ms = (busted.gettime() - testStartTime) * 1000 local string fileTestCount = fileTestCount + 1 diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 348c3112..588386b7 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -1,12 +1,11 @@ local xml = require 'pl.xml' -local socket = require("socket") local string = require("string") return function(options) local busted = require 'busted' local handler = require 'busted.outputHandlers.base'() local top = { - start_time = socket.gettime(), + start_time = busted.gettime(), xml_doc = xml.new('testsuites', { tests = 0, errors = 0, @@ -20,7 +19,7 @@ return function(options) handler.suiteStart = function(suite, count, total) local suite = { - start_time = socket.gettime(), + start_time = busted.gettime(), xml_doc = xml.new('testsuite', { name = 'Run ' .. count .. ' of ' .. total, tests = 0, @@ -38,7 +37,7 @@ return function(options) end local function elapsed(start_time) - return string.format("%.2f", (socket.gettime() - start_time)) + return string.format("%.2f", (busted.gettime() - start_time)) end handler.suiteEnd = function(suite, count, total) @@ -74,7 +73,7 @@ return function(options) end handler.testStart = function(element, parent) - testStartTime = socket.gettime() + testStartTime = busted.gettime() testcase_node = xml.new('testcase', { classname = element.trace.short_src .. ':' .. element.trace.currentline, name = handler.getFullName(element), From c7255569a59128d92a4a2def3ed51d9bc5adb35c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 17 Jan 2016 23:05:46 -0800 Subject: [PATCH 257/293] Export time functions to busted public API --- busted/init.lua | 2 ++ spec/export_spec.lua | 2 ++ 2 files changed, 4 insertions(+) diff --git a/busted/init.lua b/busted/init.lua index fa49b3c2..3d954ebd 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -105,7 +105,9 @@ local function init(busted) busted.exportApi('bindfenv', busted.bindfenv) busted.exportApi('fail', busted.fail) + busted.exportApi('gettime', busted.gettime) busted.exportApi('parent', busted.context.parent) + busted.exportApi('sleep', busted.sleep) busted.exportApi('version', busted.version) busted.bindfenv(assert, 'error', busted.fail) diff --git a/spec/export_spec.lua b/spec/export_spec.lua index 24b782be..116f059c 100644 --- a/spec/export_spec.lua +++ b/spec/export_spec.lua @@ -74,7 +74,9 @@ describe('tests require "busted"', function() it('exports other functions/variables', function() assert.is_function(require 'busted'.bindfenv) assert.is_function(require 'busted'.fail) + assert.is_function(require 'busted'.gettime) assert.is_function(require 'busted'.parent) + assert.is_function(require 'busted'.sleep) assert.is_string(require 'busted'.version) end) From e206c9ccf24dd6e714513d2f573f1c1226e93948 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 21 Jan 2016 17:05:46 -0800 Subject: [PATCH 258/293] Refactor test execution timing Move the computation and recording of test execution time to the core and insert the start/end time and duration of each block into its context for output handlers to consume and report. --- busted/core.lua | 11 ++++++++++- busted/outputHandlers/base.lua | 8 ++++---- busted/outputHandlers/gtest.lua | 13 +++---------- busted/outputHandlers/junit.lua | 32 ++++++++++++++++---------------- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index c13426a0..8b2c4044 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -192,6 +192,12 @@ return function() function busted.safe_publish(descriptor, channel, element, ...) local args = {...} local n = select('#', ...) + if channel[2] == 'start' then + element.starttime = busted.gettime() + elseif channel[2] == 'end' then + element.endtime = busted.gettime() + element.duration = element.starttime and (element.endtime - element.starttime) + end local status = busted.safe(descriptor, function() busted.publish(channel, element, unpack(args, 1, n)) end, element) @@ -261,7 +267,10 @@ return function() attributes = attributes or {}, name = name, run = fn, - trace = trace + trace = trace, + starttime = nil, + endtime = nil, + duration = nil, } busted.context.attach(plugin) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 3b0a1ca3..0dc17a7f 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -82,8 +82,8 @@ return function() return handler.endTime - handler.startTime end - handler.baseSuiteStart = function() - handler.startTime = busted.gettime() + handler.baseSuiteStart = function(suite) + handler.startTime = suite.starttime return nil, true end @@ -101,8 +101,8 @@ return function() return nil, true end - handler.baseSuiteEnd = function() - handler.endTime = busted.gettime() + handler.baseSuiteEnd = function(suite) + handler.endTime = suite.endtime return nil, true end diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index ce003dae..74237496 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -60,10 +60,6 @@ return function(options) local failureCount = 0 local errorCount = 0 - local suiteStartTime - local fileStartTime - local testStartTime - local pendingDescription = function(pending) local name = pending.name local string = '' @@ -171,7 +167,6 @@ return function(options) end handler.suiteStart = function(suite, count, total, randomseed) - suiteStartTime = busted.gettime() if total > 1 then io.write(repeatSuiteString:format(count, total)) end @@ -186,7 +181,7 @@ return function(options) end handler.suiteEnd = function(suite, count, total) - local elapsedTime_ms = (busted.gettime() - suiteStartTime) * 1000 + local elapsedTime_ms = suite.duration * 1000 local tests = (testCount == 1 and 'test' or 'tests') local files = (fileCount == 1 and 'file' or 'files') io.write(globalTeardown) @@ -198,7 +193,6 @@ return function(options) end handler.fileStart = function(file) - fileStartTime = busted.gettime() fileTestCount = 0 io.write(fileStartString:format(file.name)) io.flush() @@ -206,7 +200,7 @@ return function(options) end handler.fileEnd = function(file) - local elapsedTime_ms = (busted.gettime() - fileStartTime) * 1000 + local elapsedTime_ms = file.duration * 1000 local tests = (fileTestCount == 1 and 'test' or 'tests') fileCount = fileCount + 1 io.write(fileEndString:format(fileTestCount, tests, file.name, elapsedTime_ms)) @@ -215,7 +209,6 @@ return function(options) end handler.testStart = function(element, parent) - testStartTime = busted.gettime() io.write(runString:format(getFullName(element))) io.flush() @@ -223,7 +216,7 @@ return function(options) end handler.testEnd = function(element, parent, status, debug) - local elapsedTime_ms = (busted.gettime() - testStartTime) * 1000 + local elapsedTime_ms = element.duration * 1000 local string fileTestCount = fileTestCount + 1 diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 09617f9b..5d4408ad 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -15,16 +15,14 @@ return function(options) } local stack = {} local testcase_node - local testStartTime - local output_file_name if 'table' == type(options.arguments) then --the first argument should be the name of the xml file. output_file_name = options.arguments[1] end handler.suiteStart = function(suite, count, total) - local suite = { - start_time = busted.gettime(), + local suite_xml = { + start_time = suite.starttime, xml_doc = xml.new('testsuite', { name = 'Run ' .. count .. ' of ' .. total, tests = 0, @@ -34,26 +32,30 @@ return function(options) timestamp = os.date('!%Y-%m-%dT%H:%M:%S'), }) } - top.xml_doc:add_direct_child(suite.xml_doc) + top.xml_doc:add_direct_child(suite_xml.xml_doc) table.insert(stack, top) - top = suite + top = suite_xml return nil, true end + local function formatDuration(duration) + return string.format("%.2f", duration) + end + local function elapsed(start_time) - return string.format("%.2f", (busted.gettime() - start_time)) + return formatDuration(busted.gettime() - start_time) end handler.suiteEnd = function(suite, count, total) - local suite = top - suite.xml_doc.attr.time = elapsed(suite.start_time) + local suite_xml = top + suite_xml.xml_doc.attr.time = formatDuration(suite.duration) top = table.remove(stack) - top.xml_doc.attr.tests = top.xml_doc.attr.tests + suite.xml_doc.attr.tests - top.xml_doc.attr.errors = top.xml_doc.attr.errors + suite.xml_doc.attr.errors - top.xml_doc.attr.failures = top.xml_doc.attr.failures + suite.xml_doc.attr.failures - top.xml_doc.attr.skip = top.xml_doc.attr.skip + suite.xml_doc.attr.skip + top.xml_doc.attr.tests = top.xml_doc.attr.tests + suite_xml.xml_doc.attr.tests + top.xml_doc.attr.errors = top.xml_doc.attr.errors + suite_xml.xml_doc.attr.errors + top.xml_doc.attr.failures = top.xml_doc.attr.failures + suite_xml.xml_doc.attr.failures + top.xml_doc.attr.skip = top.xml_doc.attr.skip + suite_xml.xml_doc.attr.skip return nil, true end @@ -88,7 +90,6 @@ return function(options) end handler.testStart = function(element, parent) - testStartTime = busted.gettime() testcase_node = xml.new('testcase', { classname = element.trace.short_src .. ':' .. element.trace.currentline, name = handler.getFullName(element), @@ -100,8 +101,7 @@ return function(options) handler.testEnd = function(element, parent, status) top.xml_doc.attr.tests = top.xml_doc.attr.tests + 1 - testcase_node.time = elapsed(testStartTime) - testStartTime = nil + testcase_node.time = formatDuration(element.duration) if status == 'success' then testStatus(element, parent, nil, 'success') From a024b2e147904475f261e746762acc2be72b761f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 12 Feb 2016 15:11:24 -0800 Subject: [PATCH 259/293] Refactor cl_spec tests variable names Rename `exitcode` to `errcnt` since the variable is not really an exit code, but rather an error count. There are only a few places where the exit code is actually used, so in these places keep the `exitcode` variable name. --- spec/cl_spec.lua | 264 +++++++++++++++++++++++------------------------ 1 file changed, 132 insertions(+), 132 deletions(-) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index c2856173..abe480a3 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -38,104 +38,104 @@ end describe('Tests the busted command-line options', function() it('tests running with --tags specified', function() - local success, exitcode = executeBusted('--pattern=_tags.lua$') + local success, errcnt = executeBusted('--pattern=_tags.lua$') assert.is_false(success) - assert.is_equal(8, exitcode) - success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1') + assert.is_equal(8, errcnt) + success, errcnt = executeBusted('--pattern=_tags.lua$ --tags=tag1') assert.is_false(success) - assert.is_equal(3, exitcode) - success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1,tag2') + assert.is_equal(3, errcnt) + success, errcnt = executeBusted('--pattern=_tags.lua$ --tags=tag1,tag2') assert.is_false(success) - assert.is_equal(4, exitcode) - success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1 --tags=tag2') + assert.is_equal(4, errcnt) + success, errcnt = executeBusted('--pattern=_tags.lua$ --tags=tag1 --tags=tag2') assert.is_false(success) - assert.is_equal(4, exitcode) + assert.is_equal(4, errcnt) end) it('tests running with --exclude-tags specified', function() - local success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') + local success, errcnt = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag1,tag2,dtag1,dtag2') assert.is_true(success) - assert.is_equal(0, exitcode) - success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') + assert.is_equal(0, errcnt) + success, errcnt = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag2,dtag1,dtag2') assert.is_false(success) - assert.is_equal(2, exitcode) - success, exitcode = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag2 --exclude-tags=dtag1,dtag2') + assert.is_equal(2, errcnt) + success, errcnt = executeBusted('--pattern=_tags.lua$ --exclude-tags=tag2 --exclude-tags=dtag1,dtag2') assert.is_false(success) - assert.is_equal(2, exitcode) + assert.is_equal(2, errcnt) end) it('tests running with --tags and --exclude-tags specified', function () - local success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') + local success, errcnt = executeBusted('--pattern=_tags.lua$ --tags=tag1 --exclude-tags=tag1') assert.is_false(success) - success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') + success, errcnt = executeBusted('--pattern=_tags.lua$ --tags=tag3 --exclude-tags=tag4') assert.is_false(success) end) it('tests running with --tags specified in describe', function () - local success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=dtag1') + local success, errcnt = executeBusted('--pattern=_tags.lua$ --tags=dtag1') assert.is_false(success) - assert.is_equal(5, exitcode) - success, exitcode = executeBusted('--pattern=_tags.lua$ --tags=dtag2') + assert.is_equal(5, errcnt) + success, errcnt = executeBusted('--pattern=_tags.lua$ --tags=dtag2') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) it('tests running with --filter specified', function () - local success, exitcode = executeBusted('--pattern=_filter.lua$') + local success, errcnt = executeBusted('--pattern=_filter.lua$') assert.is_false(success) - assert.is_equal(8, exitcode) - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern1"') + assert.is_equal(8, errcnt) + success, errcnt = executeBusted('--pattern=_filter.lua$ --filter="pattern1"') assert.is_false(success) - assert.is_equal(3, exitcode) - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern2"') + assert.is_equal(3, errcnt) + success, errcnt = executeBusted('--pattern=_filter.lua$ --filter="pattern2"') assert.is_false(success) - assert.is_equal(2, exitcode) - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern1" --filter="pattern2"') + assert.is_equal(2, errcnt) + success, errcnt = executeBusted('--pattern=_filter.lua$ --filter="pattern1" --filter="pattern2"') assert.is_false(success) - assert.is_equal(4, exitcode) + assert.is_equal(4, errcnt) end) it('tests running with --filter-out specified', function () - local success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="pattern1"') + local success, errcnt = executeBusted('--pattern=_filter.lua$ --filter-out="pattern1"') assert.is_false(success) - assert.is_equal(6, exitcode) - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="pattern%d"') + assert.is_equal(6, errcnt) + success, errcnt = executeBusted('--pattern=_filter.lua$ --filter-out="pattern%d"') assert.is_false(success) - assert.is_equal(5, exitcode) - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="patt1" --filter-out="patt2"') + assert.is_equal(5, errcnt) + success, errcnt = executeBusted('--pattern=_filter.lua$ --filter-out="patt1" --filter-out="patt2"') assert.is_false(success) - assert.is_equal(3, exitcode) - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter-out="patt.*(%d)"') + assert.is_equal(3, errcnt) + success, errcnt = executeBusted('--pattern=_filter.lua$ --filter-out="patt.*(%d)"') assert.is_true(success) end) it('tests running with --filter and --filter-out specified', function () - local success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') + local success, errcnt = executeBusted('--pattern=_filter.lua$ --filter="pattern3" --filter-out="patt.*[12]"') assert.is_true(success) end) it('tests running with --filter specified in describe', function () - local success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="patt1"') + local success, errcnt = executeBusted('--pattern=_filter.lua$ --filter="patt1"') assert.is_false(success) - assert.is_equal(5, exitcode) - success, exitcode = executeBusted('--pattern=_filter.lua$ --filter="patt2"') + assert.is_equal(5, errcnt) + success, errcnt = executeBusted('--pattern=_filter.lua$ --filter="patt2"') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) it('tests running with --lazy specified', function() - local success, exitcode = executeBusted('--lazy --pattern=_tags.lua$') + local success, errcnt = executeBusted('--lazy --pattern=_tags.lua$') assert.is_false(success) - assert.is_equal(7, exitcode) - success, exitcode = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1') + assert.is_equal(7, errcnt) + success, errcnt = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1') assert.is_false(success) - assert.is_equal(2, exitcode) - success, exitcode = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1,tag2') + assert.is_equal(2, errcnt) + success, errcnt = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1,tag2') assert.is_false(success) - assert.is_equal(3, exitcode) - success, exitcode = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1 --tags=tag2') + assert.is_equal(3, errcnt) + success, errcnt = executeBusted('--lazy --pattern=_tags.lua$ --tags=tag1 --tags=tag2') assert.is_false(success) - assert.is_equal(3, exitcode) + assert.is_equal(3, errcnt) end) it('tests running with -l specified', function() @@ -155,76 +155,76 @@ describe('Tests the busted command-line options', function() end) it('tests running with --lpath specified', function() - local success, exitcode = executeBusted('--lpath="spec/?.lua" spec/cl_lua_path.lua') + local success, errcnt = executeBusted('--lpath="spec/?.lua" spec/cl_lua_path.lua') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) it('tests running with --lang specified', function() - local success, exitcode = executeBusted('--pattern=cl_success.lua$ --lang=en') + local success, errcnt = executeBusted('--pattern=cl_success.lua$ --lang=en') assert.is_true(success) - assert.is_equal(0, exitcode) - success, exitcode = executeBusted('--pattern=cl_success --lang=not_found_here') + assert.is_equal(0, errcnt) + success, errcnt = executeBusted('--pattern=cl_success --lang=not_found_here') assert.is_false(success) end) it('tests running with --version specified', function() - local success, exitcode = executeBusted('--version') + local success, errcnt = executeBusted('--version') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) it('tests running with --help specified', function() - local success, exitcode = executeBusted('--help') + local success, errcnt = executeBusted('--help') assert.is_false(success) end) it('tests running a non-compiling testfile', function() - local success, exitcode = executeBusted('--pattern=cl_compile_fail.lua$') + local success, errcnt = executeBusted('--pattern=cl_compile_fail.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) it('tests running a testfile throwing errors when being run', function() - local success, exitcode = executeBusted('--pattern=cl_execute_fail.lua$') + local success, errcnt = executeBusted('--pattern=cl_execute_fail.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) it('tests running with --output specified', function() - local success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=TAP') + local success, errcnt = executeBusted('--pattern=cl_success.lua$ --output=TAP') assert.is_true(success) - assert.is_equal(0, exitcode) - success, exitcode = executeBusted('--pattern=cl_two_failures.lua$ --output=not_found_here') + assert.is_equal(0, errcnt) + success, errcnt = executeBusted('--pattern=cl_two_failures.lua$ --output=not_found_here') assert.is_false(success) - assert.is_equal(2, exitcode) + assert.is_equal(2, errcnt) end) it('tests running with --output specified with module in lua path', function() - local success, exitcode = executeBusted('--pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') + local success, errcnt = executeBusted('--pattern=cl_success.lua$ --output=busted.outputHandlers.TAP') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) it('tests no tests to exit with a fail-exitcode', function() - local success, exitcode = executeBusted('--pattern=this_filename_does_simply_not_exist$') + local success, exitcode = execute(busted_cmd ..' --pattern=this_filename_does_simply_not_exist$') assert.is_false(success) assert.is_equal(1, exitcode) end) it('can switch interpreters', function() - local success, exitcode, out = executeBusted('--lua=spec/lua.lua spec/cl_success.lua') + local success, errcnt, out = executeBusted('--lua=spec/lua.lua spec/cl_success.lua') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) assert.equal('bin/busted --ignore-lua --lua=spec/lua.lua spec/cl_success.lua\n', out) end) end) describe('Tests failing tests through the commandline', function() it('tests failing setup/before_each/after_each/teardown functions', function() - local success, exitcode = executeBusted('--pattern=cl_failing_support.lua$') + local success, errcnt = executeBusted('--pattern=cl_failing_support.lua$') assert.is_false(success) - assert.is_equal(16, exitcode) + assert.is_equal(16, errcnt) end) it('tests failing support functions as errors', function() @@ -236,62 +236,62 @@ end) describe('Test busted running standalone', function() it('tests running with --tags specified', function() - local success, exitcode = executeLua('spec/cl_standalone.lua') + local success, errcnt = executeLua('spec/cl_standalone.lua') assert.is_false(success) - assert.is_equal(3, exitcode) - success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1') + assert.is_equal(3, errcnt) + success, errcnt = executeLua('spec/cl_standalone.lua --tags=tag1') assert.is_false(success) - assert.is_equal(2, exitcode) - success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1,tag2') + assert.is_equal(2, errcnt) + success, errcnt = executeLua('spec/cl_standalone.lua --tags=tag1,tag2') assert.is_false(success) - assert.is_equal(3, exitcode) + assert.is_equal(3, errcnt) end) it('tests running with --exclude-tags specified', function() - local success, exitcode = executeLua('spec/cl_standalone.lua --exclude-tags=tag1,tag2') + local success, errcnt = executeLua('spec/cl_standalone.lua --exclude-tags=tag1,tag2') assert.is_true(success) - assert.is_equal(0, exitcode) - success, exitcode = executeLua('spec/cl_standalone.lua --exclude-tags=tag2') + assert.is_equal(0, errcnt) + success, errcnt = executeLua('spec/cl_standalone.lua --exclude-tags=tag2') assert.is_false(success) - assert.is_equal(2, exitcode) + assert.is_equal(2, errcnt) end) it('tests running with --tags and --exclude-tags specified', function () - local success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag1 --exclude-tags=tag1') + local success, errcnt = executeLua('spec/cl_standalone.lua --tags=tag1 --exclude-tags=tag1') assert.is_false(success) - success, exitcode = executeLua('spec/cl_standalone.lua --tags=tag3 --exclude-tags=tag4') + success, errcnt = executeLua('spec/cl_standalone.lua --tags=tag3 --exclude-tags=tag4') assert.is_true(success) end) it('tests running with --helper specified', function () - local success, exitcode = executeLua('spec/cl_standalone.lua --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown,--fail-after-each"') + local success, errcnt = executeLua('spec/cl_standalone.lua --helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown,--fail-after-each"') assert.is_false(success) - assert.is_equal(9, exitcode) + assert.is_equal(9, errcnt) end) it('tests running with --version specified', function() - local success, exitcode = executeLua('spec/cl_standalone.lua --version') + local success, errcnt = executeLua('spec/cl_standalone.lua --version') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) it('tests running with --help specified', function() - local success, exitcode = executeLua('spec/cl_standalone.lua --help') + local success, errcnt = executeLua('spec/cl_standalone.lua --help') assert.is_false(success) end) end) describe('Test busted command-line runner', function() it('runs standalone spec', function() - local success, exitcode = executeBusted('spec/cl_standalone.lua') + local success, errcnt = executeBusted('spec/cl_standalone.lua') assert.is_false(success) - assert.is_equal(3, exitcode) - success, exitcode = executeBusted('--tags=tag1 spec/cl_standalone.lua') + assert.is_equal(3, errcnt) + success, errcnt = executeBusted('--tags=tag1 spec/cl_standalone.lua') assert.is_false(success) - assert.is_equal(2, exitcode) - success, exitcode = executeBusted('--tags=tag1,tag2 spec/cl_standalone.lua') + assert.is_equal(2, errcnt) + success, errcnt = executeBusted('--tags=tag1,tag2 spec/cl_standalone.lua') assert.is_false(success) - assert.is_equal(3, exitcode) + assert.is_equal(3, errcnt) end) end) @@ -442,12 +442,12 @@ describe('Tests error messages through the command line', function() end, function() end) if noGC then pending('no __gc metamethod support') end - local success, exitcode, result = executeBusted('--pattern=cl_gc_error.lua$') + local success, errcnt, result = executeBusted('--pattern=cl_gc_error.lua$') local err = result:match('Error %-> (.-)\n') local errmsg = result:match('\n([^\n]-%(spec[/\\].-%))\n') local expected = 'error in __gc metamethod (spec/cl_gc_error.lua:5: gc error)' assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) assert.is_truthy(err) assert.is_equal(normpath(expected), errmsg) end) @@ -494,10 +494,10 @@ end) describe('Tests pending through the commandline', function() it('skips tests inside pending scope', function() - local success, exitcode - success, exitcode = executeBusted('--pattern=cl_pending.lua$') + local success, errcnt + success, errcnt = executeBusted('--pattern=cl_pending.lua$') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) it('detects tests as pending', function() @@ -521,15 +521,15 @@ end) describe('Tests random seed through the commandline', function() it('test seed value', function() - local success, exitcode - success, exitcode = executeBusted('--seed=12345 --pattern=cl_random_seed.lua$') + local success, errcnt + success, errcnt = executeBusted('--seed=12345 --pattern=cl_random_seed.lua$') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) it('test invalid seed value exits with error', function() - local success, exitcode - success, exitcode = executeBusted('--seed=abcd --pattern=cl_random_seed.lua$') + local success, errcnt + success, errcnt = executeBusted('--seed=abcd --pattern=cl_random_seed.lua$') assert.is_false(success) end) @@ -549,9 +549,9 @@ end) describe('Tests shuffle commandline option', function() for _, opt in ipairs({ '--shuffle', '--shuffle-tests' }) do it('forces test shuffling for non-randomized tests, ' .. opt, function() - local success, exitcode = executeBusted(opt .. ' --pattern=cl_randomize.lua$') + local success, errcnt = executeBusted(opt .. ' --pattern=cl_randomize.lua$') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) end end) @@ -559,48 +559,48 @@ end) describe('Tests sort commandline option', function() for _, opt in ipairs({ '--sort', '--sort-tests' }) do it('sorts tests by name, ' .. opt, function() - local success, exitcode = executeBusted(opt .. ' --pattern=cl_sort.lua$') + local success, errcnt = executeBusted(opt .. ' --pattern=cl_sort.lua$') assert.is_true(success) - assert.is_equal(0, exitcode) + assert.is_equal(0, errcnt) end) end end) describe('Tests repeat commandline option', function() it('forces tests to repeat n times', function() - local success, exitcode = executeBusted('--repeat=2 --pattern=cl_two_failures.lua$') + local success, errcnt = executeBusted('--repeat=2 --pattern=cl_two_failures.lua$') assert.is_false(success) - assert.is_equal(4, exitcode) + assert.is_equal(4, errcnt) end) it('exits with error when repeat is invalid', function() - local success, exitcode - success, exitcode = executeBusted('--repeat=abc --pattern=cl_success.lua$') + local success, errcnt + success, errcnt = executeBusted('--repeat=abc --pattern=cl_success.lua$') assert.is_false(success) end) end) describe('Tests no-keep-going commandline option', function() it('skips all tests after first error', function() - local success, exitcode = executeBusted('--no-keep-going --pattern=cl_two_failures.lua$') + local success, errcnt = executeBusted('--no-keep-going --pattern=cl_two_failures.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) end) describe('Tests no-recursive commandline option', function() it('does not run any tests in subdirectories', function() - local success, exitcode = executeBusted('--no-recursive --pattern=cl_two_failures.lua$ .') + local success, errcnt = executeBusted('--no-recursive --pattern=cl_two_failures.lua$ .') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) end) describe('Tests no-auto-insulate commandline option', function() it('does not insulate test files', function() - local success, exitcode = executeBusted('--no-auto-insulate --pattern=insulate_file.*.lua$') + local success, errcnt = executeBusted('--no-auto-insulate --pattern=insulate_file.*.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) end) @@ -637,47 +637,47 @@ describe('Tests Xhelper commandline option', function() end) it('forwards single option to helper script', function() - local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" --pattern=cl_success.lua$') + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" --pattern=cl_success.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) it('forwards multiple options to helper script', function() - local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each,--fail-after-each" --pattern=cl_success.lua$') + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each,--fail-after-each" --pattern=cl_success.lua$') assert.is_false(success) - assert.is_equal(2, exitcode) + assert.is_equal(2, errcnt) end) it('forwards multiple options to helper script using multiple -Xhelper', function() - local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" -Xhelper "--fail-after-each" --pattern=cl_success.lua$') + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-before-each" -Xhelper "--fail-after-each" --pattern=cl_success.lua$') assert.is_false(success) - assert.is_equal(2, exitcode) + assert.is_equal(2, errcnt) end) end) describe('Tests helper script', function() it('can add setup to test suite', function() - local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-setup" --pattern=cl_two_failures.lua$') + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-setup" --pattern=cl_two_failures.lua$') assert.is_false(success) - assert.is_equal(1, exitcode) + assert.is_equal(1, errcnt) end) it('can add teardown to test suite', function() - local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown" --pattern=cl_two_failures.lua$') + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-teardown" --pattern=cl_two_failures.lua$') assert.is_false(success) - assert.is_equal(3, exitcode) + assert.is_equal(3, errcnt) end) it('runs setup/teardown for mutiple runs', function() - local success, exitcode = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') assert.is_false(success) - assert.is_equal(4, exitcode) + assert.is_equal(4, errcnt) end) it('runs setup/teardown for mutiple runs with --lazy', function() - local success, exitcode = executeBusted('--lazy --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') + local success, errcnt = executeBusted('--lazy --helper=spec/cl_helper_script.lua -Xhelper "--fail-setup,--fail-teardown" --pattern=cl_success.lua$ --repeat=2') assert.is_false(success) - assert.is_equal(4, exitcode) + assert.is_equal(4, errcnt) end) end) From 294179c5de6a6e346c7bfe7cda0fb0bcd6a8bd69 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 12 Feb 2016 14:45:18 -0800 Subject: [PATCH 260/293] Fix error reporting for errors in message handlers When an error occurs in a suite start/end handler, retrieving the trace information yields another error because there is no file associated with the code that threw the original error. This then triggers another error to be thrown, resulting in an infinite loop of error throwing and error catching. This change fixes this by checking for a valid file context before accessing the subfields for the file. When a 'failure' is thrown (from an `assert`) inside a test start/end handler, the failure and error counters are not incremented if the test passes. Failures in a test start/end handler should be logged as errors outside tests, just as failures in support functions are logged as errors outside tests. Also use safe_publish for suite reset to catch any errors that may occur in a suite reset handler. --- busted/core.lua | 22 ++++++++++-- busted/execute.lua | 15 ++++---- busted/init.lua | 4 +-- busted/modules/files/lua.lua | 5 ++- busted/modules/files/moonscript.lua | 3 +- busted/modules/files/terra.lua | 2 +- spec/cl_helper_script.lua | 55 +++++++++++++++++++++++++++++ spec/cl_spec.lua | 30 ++++++++++++++++ 8 files changed, 118 insertions(+), 18 deletions(-) diff --git a/busted/core.lua b/busted/core.lua index c13426a0..92f6e80f 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -62,6 +62,11 @@ return function() busted.status = require 'busted.status' function busted.getTrace(element, level, msg) + local function trimTrace(info) + local index = info.traceback:find('\n%s*%[C]') + info.traceback = info.traceback:sub(1, index) + return info + end level = level or 3 local thisdir = path.dirname(debug.getinfo(1, 'Sl').source) @@ -76,14 +81,14 @@ return function() info.message = msg local file = busted.getFile(element) - return file.getTrace(file.name, info) + return file and file.getTrace(file.name, info) or trimTrace(info) end function busted.rewriteMessage(element, message, trace) local file = busted.getFile(element) local msg = hasToString(message) and tostring(message) msg = msg or (message ~= nil and pretty.write(message) or 'Nil error') - msg = (file.rewriteMessage and file.rewriteMessage(file.name, msg) or msg) + msg = (file and file.rewriteMessage and file.rewriteMessage(file.name, msg) or msg) local hasFileLine = msg:match('^[^\n]-:%d+: .*') if not hasFileLine then @@ -180,8 +185,19 @@ return function() status = 'error' trace = busted.getTrace(element, 3, ret[2]) message = busted.rewriteMessage(element, ret[2], trace) + elseif status == 'failure' and descriptor ~= 'it' then + -- Only 'it' blocks can generate test failures. Failures in all + -- other blocks are errors outside the test. + status = 'error' end - busted.publish({ status, descriptor }, element, busted.context.parent(element), message, trace) + -- Note: descriptor may be different from element.descriptor when + -- safe_publish is used (i.e. for test start/end). The safe_publish + -- descriptor needs to be different for 'it' blocks so that we can + -- detect that a 'failure' in a test start/end handler is not really + -- a test failure, but rather an error outside the test, much like a + -- failure in a support function (i.e. before_each/after_each or + -- setup/teardown). + busted.publish({ status, element.descriptor }, element, busted.context.parent(element), message, trace) end ret[1] = busted.status(status) diff --git a/busted/execute.lua b/busted/execute.lua index 7f90298c..4f3bcf93 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -3,7 +3,7 @@ return function(busted) local block = require 'busted.block'(busted) local function execute(runs, options) - busted.subscribe({'suite', 'reset'}, function() + local function suite_reset() local oldctx = busted.context.get() local children = busted.context.children(oldctx) @@ -21,17 +21,18 @@ return function(busted) end busted.randomseed = tonumber(options.seed) or os.time() - - return nil, true - end) + end for i = 1, runs do + local root = busted.context.get() + local seed = (busted.randomize and busted.randomseed or nil) + if i > 1 then - busted.publish({ 'suite', 'reset' }) + suite_reset() + root = busted.context.get() + busted.safe_publish('suite', { 'suite', 'reset' }, root, i, runs) end - local root = busted.context.get() - local seed = (busted.randomize and busted.randomseed or nil) if busted.safe_publish('suite', { 'suite', 'start' }, root, i, runs, seed) then if block.setup(root) then busted.execute() diff --git a/busted/init.lua b/busted/init.lua index 3d954ebd..f472dd3c 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -36,7 +36,7 @@ local function init(busted) if pass then local status = busted.status('success') - if busted.safe_publish('it', { 'test', 'start' }, element, parent) then + if busted.safe_publish('test', { 'test', 'start' }, element, parent) then status:update(busted.safe('it', element.run, element)) if finally then block.reject('pending', element) @@ -45,7 +45,7 @@ local function init(busted) else status = busted.status('error') end - busted.safe_publish('it', { 'test', 'end' }, element, parent, tostring(status)) + busted.safe_publish('test', { 'test', 'end' }, element, parent, tostring(status)) end block.dexecAll('after_each', ancestor, true) diff --git a/busted/modules/files/lua.lua b/busted/modules/files/lua.lua index a4218f6d..6396f0ca 100644 --- a/busted/modules/files/lua.lua +++ b/busted/modules/files/lua.lua @@ -2,17 +2,16 @@ local path = require 'pl.path' local ret = {} -local getTrace = function(filename, info) +local getTrace = function(filename, info) local index = info.traceback:find('\n%s*%[C]') info.traceback = info.traceback:sub(1, index) - return info, false + return info end ret.match = function(busted, filename) return path.extension(filename) == '.lua' end - ret.load = function(busted, filename) local file, err = loadfile(filename) if not file then diff --git a/busted/modules/files/moonscript.lua b/busted/modules/files/moonscript.lua index 145b942f..067d2859 100644 --- a/busted/modules/files/moonscript.lua +++ b/busted/modules/files/moonscript.lua @@ -68,7 +68,7 @@ end local ret = {} -local getTrace = function(filename, info) +local getTrace = function(filename, info) local index = info.traceback:find('\n%s*%[C]') info.traceback = info.traceback:sub(1, index) @@ -96,7 +96,6 @@ ret.match = function(busted, filename) return ok and path.extension(filename) == '.moon' end - ret.load = function(busted, filename) local file, err = moonscript.loadfile(filename) if not file then diff --git a/busted/modules/files/terra.lua b/busted/modules/files/terra.lua index 02956f76..2e13350b 100644 --- a/busted/modules/files/terra.lua +++ b/busted/modules/files/terra.lua @@ -3,7 +3,7 @@ local path = require 'pl.path' local ret = {} local ok, terralib = pcall(function() return require 'terralib' end) -local getTrace = function(filename, info) +local getTrace = function(filename, info) local index = info.traceback:find('\n%s*%[C]') info.traceback = info.traceback:sub(1, index) return info diff --git a/spec/cl_helper_script.lua b/spec/cl_helper_script.lua index 19967830..f1af2995 100644 --- a/spec/cl_helper_script.lua +++ b/spec/cl_helper_script.lua @@ -4,6 +4,7 @@ local setup = require 'busted'.setup local teardown = require 'busted'.teardown local before_each = require 'busted'.before_each local after_each = require 'busted'.after_each +local subscribe = require 'busted'.subscribe local assert = require 'busted'.assert local cli = require 'cliargs' @@ -12,6 +13,15 @@ cli:flag('--fail-setup', 'force setup to fail') cli:flag('--fail-teardown', 'force teardown to fail') cli:flag('--fail-before-each', 'force before each to fail') cli:flag('--fail-after-each', 'force after each to fail') +cli:flag('--fail-suite-reset', 'force suite reset handler to fail') +cli:flag('--fail-suite-start', 'force suite start handler to fail') +cli:flag('--fail-suite-end', 'force suite end handler to fail') +cli:flag('--fail-file-start', 'force file start handler to fail') +cli:flag('--fail-file-end', 'force file end handler to fail') +cli:flag('--fail-describe-start', 'force describe start handler to fail') +cli:flag('--fail-describe-end', 'force describe end handler to fail') +cli:flag('--fail-test-start', 'force test start handler to fail') +cli:flag('--fail-test-end', 'force test end handler to fail') local cliArgs = cli:parse(arg) @@ -30,3 +40,48 @@ end) after_each(function() assert(not cliArgs['fail-after-each']) end) + +subscribe({'suite', 'reset'}, function() + assert(not cliArgs['fail-suite-reset']) + return nil, true +end) + +subscribe({'suite', 'start'}, function() + assert(not cliArgs['fail-suite-start']) + return nil, true +end) + +subscribe({'suite', 'end'}, function() + assert(not cliArgs['fail-suite-end']) + return nil, true +end) + +subscribe({'file', 'start'}, function() + assert(not cliArgs['fail-file-start']) + return nil, true +end) + +subscribe({'file', 'end'}, function() + assert(not cliArgs['fail-file-end']) + return nil, true +end) + +subscribe({'describe', 'start'}, function() + assert(not cliArgs['fail-describe-start']) + return nil, true +end) + +subscribe({'describe', 'end'}, function() + assert(not cliArgs['fail-describe-end']) + return nil, true +end) + +subscribe({'test', 'start'}, function() + assert(not cliArgs['fail-test-start']) + return nil, true +end) + +subscribe({'test', 'end'}, function() + assert(not cliArgs['fail-test-end']) + return nil, true +end) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index abe480a3..6b5a587f 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -679,6 +679,36 @@ describe('Tests helper script', function() assert.is_false(success) assert.is_equal(4, errcnt) end) + + it('can subscribe to suite start/reset', function() + local success, errcnt, result = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-suite-start,--fail-suite-reset" --pattern=cl_success.lua$ --repeat=2') + assert.is_false(success) + assert.is_equal(3, errcnt) + end) + + it('can subscribe to suite end', function() + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-suite-end" --pattern=cl_success.lua$') + assert.is_false(success) + assert.is_equal(0, errcnt) + end) + + it('can subscribe to file start/end', function() + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-file-start,--fail-file-end" --pattern=cl_success.lua$') + assert.is_false(success) + assert.is_equal(2, errcnt) + end) + + it('can subscribe to describe start/end', function() + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-describe-start,--fail-describe-end" --pattern=cl_success.lua$') + assert.is_false(success) + assert.is_equal(2, errcnt) + end) + + it('can subscribe to test start/end', function() + local success, errcnt = executeBusted('--helper=spec/cl_helper_script.lua -Xhelper "--fail-test-start,--fail-test-end" --pattern=cl_two_failures.lua$') + assert.is_false(success) + assert.is_equal(4, errcnt) + end) end) describe('Tests strict with helper script', function() From b2df646196088153375605970fe6d96b2f74db75 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 15 Feb 2016 15:56:24 -0800 Subject: [PATCH 261/293] Update auto completion scripts --- completions/bash/busted.bash | 6 ++++++ completions/zsh/_busted | 2 ++ 2 files changed, 8 insertions(+) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index faf86377..30939821 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -111,6 +111,10 @@ _busted() { _filedir return 0 ;; + --lua) + _filedir + return 0 + ;; --helper) _filedir return 0 @@ -158,6 +162,8 @@ _busted() { -t --tags= --exclude-tags= -m --lpath= --cpath= -r --run= + --lua= + --ignore-lua --filter= --filter-out= --repeat= --seed= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 9ccdd025..f75311b4 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -35,6 +35,8 @@ _busted_args=( "(-k --keep-going --no-keep-going)--no-keep-going[Quit after first error or failure]" "(-R --recursive --no-recursive)--recursive[Recurse into subdirectories]" "(-R --recursive --no-recursive)--no-recursive[Do not recurse into subdirectories]" +"--ignore-lua[Whether or not to ignore the lua directive]" +"--lua[The path to the lua interpreter busted should run under]:files:_files" "--helper[A helper script that is run before tests]:files:_files" "--loaders=[Test file loaders]:loaders:_values -s , loaders lua moonscript terra" "-Xoutput[Pass 'OPTION' as an option to the output handler. If 'OPTION' contains commas, it is split into multiple options at the commas.]: :" From e0d2e65713b4696d3861773486f3d6605277d825 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 15 Feb 2016 10:28:17 -0800 Subject: [PATCH 262/293] Fixes for using debugger --- busted/modules/test_file_loader.lua | 2 +- busted/outputHandlers/gtest.lua | 2 +- busted/runner.lua | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 43af5c77..2f4b05b1 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -22,7 +22,7 @@ return function(busted, loaders) fileList = getfiles(rootFile) fileList = tablex.filter(fileList, function(filename) - return path.basename(filename):find(pattern) + return path.basename(filename):find(pattern or '') end) fileList = tablex.filter(fileList, function(filename) diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index ce003dae..69a5504c 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -4,7 +4,7 @@ local term = require 'term' local colors -local isatty = term.isatty(io.stdout) +local isatty = io.type(io.stdout) == 'file' and term.isatty(io.stdout) local isWindows = package.config:sub(1,1) == '\\' if isWindows and not os.getenv("ANSICON") or not isatty then diff --git a/busted/runner.lua b/busted/runner.lua index d4e983e5..b4fd6241 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -10,8 +10,9 @@ local loaded = false return function(options) if loaded then return else loaded = true end + local isatty = io.type(io.stdout) == 'file' and term.isatty(io.stdout) options = tablex.update(require 'busted.options', options or {}) - options.defaultOutput = term.isatty(io.stdout) and 'utfTerminal' or 'plainTerminal' + options.defaultOutput = isatty and 'utfTerminal' or 'plainTerminal' local busted = require 'busted.core'() From b694243979898e87995ac089a0315a9ab1a7a6f0 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 15 Feb 2016 15:57:03 -0800 Subject: [PATCH 263/293] Add `-e STATEMENT` option to run Lua statements This adds a `-e` option to the busted command-line to execute Lua statements before running any tests, analogous to the `-e` option for the Lua interpreter. --- busted/compatibility.lua | 1 + busted/modules/cli.lua | 1 + busted/runner.lua | 8 ++++++++ completions/bash/busted.bash | 5 +++++ completions/zsh/_busted | 1 + spec/cl_spec.lua | 9 +++++++++ spec/modules/cli_spec.lua | 8 ++++++++ 7 files changed, 33 insertions(+) diff --git a/busted/compatibility.lua b/busted/compatibility.lua index 2fcbb4b8..d8816a9a 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -30,6 +30,7 @@ return { if f ~= 0 then return f end end, + loadstring = loadstring or load, unpack = table.unpack or unpack, exit = function(code) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 2e6cca57..20dab81d 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -116,6 +116,7 @@ return function(options) cli:option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) end + cli:option('-e STATEMENT', 'execute statement STATEMENT', nil, processMultiOption) cli:option('-o, --output=LIBRARY', 'output library to load', defaultOutput, processOption) cli:option('-C, --directory=DIR', 'change to directory DIR before running tests. If multiple options are specified, each is interpreted relative to the previous one.', './', processDir) cli:option('-f, --config-file=FILE', 'load configuration options from FILE', nil, processOptions) diff --git a/busted/runner.lua b/busted/runner.lua index b4fd6241..daccedf7 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -5,6 +5,7 @@ local tablex = require 'pl.tablex' local term = require 'term' local utils = require 'busted.utils' local exit = require 'busted.compatibility'.exit +local loadstring = require 'busted.compatibility'.loadstring local loaded = false return function(options) @@ -77,6 +78,13 @@ return function(options) package.cpath = (cliArgs.cpath .. ';' .. package.cpath):gsub(';;',';') end + -- Load and execute commands given on the command-line + if cliArgs.e then + for k,v in ipairs(cliArgs.e) do + loadstring(v)() + end + end + -- watch for test errors and failures local failures = 0 local errors = 0 diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 30939821..815f3960 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -119,6 +119,10 @@ _busted() { _filedir return 0 ;; + -e) + # no completion available + return 0 + ;; -p|--pattern) # no completion available return 0 @@ -162,6 +166,7 @@ _busted() { -t --tags= --exclude-tags= -m --lpath= --cpath= -r --run= + -e --lua= --ignore-lua --filter= --filter-out= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index f75311b4..13e77d10 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -55,6 +55,7 @@ _busted_args=( "--exclude-tags=[Do not run tests with these #tags, takes precedence over --tags]: :" "--filter=[Only run test names matching the Lua pattern]: :" "--filter-out=[Do not run test names matching the Lua pattern, takes precedence over --filter]: :" +"-e[Execute Lua statement]: :" "(-v --verbose --no-verbose)"{-v,--verbose}"[Verbose output of errors]" "(-v --verbose --no-verbose)--no-verbose[Disable verbose output of errors]" "*:files:_files" diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index c2856173..c1746bf0 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -687,3 +687,12 @@ describe('Tests strict with helper script', function() assert.is_true(success) end) end) + +describe('Tests execute option', function() + it('will run the specified statement', function() + local success, errcnt, result = executeBusted('-e "print(\\\"hello world\\\")" --pattern=cl_success.lua$') + assert.is_true(success) + assert.is_equal(0, errcnt) + assert.is_equal('hello world', result:match('(.-)\n')) + end) +end) diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 47785b64..01b0f43b 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -38,6 +38,7 @@ describe('Tests command-line interface', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) + assert.is_nil(args.e) assert.is_nil(args.f) assert.is_nil(args['config-file']) assert.is_nil(args.shuffle) @@ -307,6 +308,12 @@ describe('Tests command-line interface', function() assert.is_equal('./path1/?.so;./path2/?.so', args.m) assert.is_equal('./path1/?.so;./path2/?.so', args.lpath) end) + + it('specify -e statement', function() + local cli = require 'busted.modules.cli'() + local args = cli:parse({ '-e', 'statement1', '-e', 'statement2' }) + assert.is_same({'statement1', 'statement2'}, args.e) + end) end) describe('Tests using .busted tasks', function() @@ -346,6 +353,7 @@ describe('Tests using .busted tasks', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) + assert.is_nil(args.e) assert.is_nil(args.f) assert.is_nil(args['config-file']) assert.is_nil(args.shuffle) From 5eeaff12f4d7f7e5b2453d7f6fc22f083d35284a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 19 Feb 2016 09:52:27 -0800 Subject: [PATCH 264/293] Output error message for bad configuration files Check that any configuration file that was specified is loaded successfully, instead of failing silently and ignoring the file. When there is an error loading in the configuration file, output an error message and exit. --- busted/modules/cli.lua | 12 +++++----- busted/modules/configuration_loader.lua | 5 ++--- spec/.hidden/.busted_bad | 14 ++++++++++++ spec/.hidden/.busted_empty | 0 spec/modules/cli_spec.lua | 26 ++++++++++++++++++++++ spec/modules/configuration_loader_spec.lua | 6 +++-- 6 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 spec/.hidden/.busted_bad create mode 100644 spec/.hidden/.busted_empty diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 20dab81d..9e6ec6d9 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -163,13 +163,15 @@ return function(options) end -- Load busted config file if available - local configFile = { } local bustedConfigFilePath = cliArgs.f or path.normpath(path.join(cliArgs.directory, '.busted')) - local bustedConfigFile = pcall(function() configFile = loadfile(bustedConfigFilePath)() end) + local bustedConfigFile = loadfile(bustedConfigFilePath) if bustedConfigFile then - local config, err = configLoader(configFile, cliArgsParsed, cliArgs) - if err then - return nil, appName .. ': error: ' .. err + local ok, config = pcall(function() + local conf, err = configLoader(bustedConfigFile(), cliArgsParsed, cliArgs) + return conf or error(err, 0) + end) + if not ok then + return nil, appName .. ': error: ' .. config else cliArgs = config end diff --git a/busted/modules/configuration_loader.lua b/busted/modules/configuration_loader.lua index 0887027d..c2504dce 100644 --- a/busted/modules/configuration_loader.lua +++ b/busted/modules/configuration_loader.lua @@ -4,7 +4,7 @@ return function() -- Function to load the .busted configuration file if available local loadBustedConfigurationFile = function(configFile, config, defaults) if type(configFile) ~= 'table' then - return config, '.busted file does not return a table.' + return nil, '.busted file does not return a table.' end local defaults = defaults or {} @@ -16,7 +16,7 @@ return function() if type(runConfig) == 'table' then config = tablex.merge(runConfig, config, true) else - return config, 'Task `' .. run .. '` not found, or not a table.' + return nil, 'Task `' .. run .. '` not found, or not a table.' end elseif type(configFile.default) == 'table' then config = tablex.merge(configFile.default, config, true) @@ -33,4 +33,3 @@ return function() return loadBustedConfigurationFile end - diff --git a/spec/.hidden/.busted_bad b/spec/.hidden/.busted_bad new file mode 100644 index 00000000..b1df1c77 --- /dev/null +++ b/spec/.hidden/.busted_bad @@ -0,0 +1,14 @@ +return { + _all = { + ['ROOT'] = {'tests'}, + }, + default = { + ['ROOT'] = {'specs'}, + ['pattern'] = '_spec%.lua$', + ['loaders'] = doesnotexist.loaders, + ['verbose'] = true, + }, + test = { + ['pattern'] = '_test%.lua$', + } +} diff --git a/spec/.hidden/.busted_empty b/spec/.hidden/.busted_empty new file mode 100644 index 00000000..e69de29b diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 01b0f43b..ca1f4d34 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -454,6 +454,32 @@ describe('Tests using .busted tasks', function() assert.is_same({'-t', '--print'}, args.Xhelper) assert.is_same({'moonscript'}, args.loaders) end) + + it('detects error in configuration file', function() + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + cli:set_name('app') + local args, err = cli:parse({ '--config-file=spec/.hidden/.busted_bad', '--run=test' }) + assert.is_nil(args) + assert.has_match('^app: error: spec/.hidden/.busted_bad:8: ', err) + assert.has_match("'doesnotexist'", err) + assert.has_match("\(a nil value\)", err) + end) + + it('detects invalid configuration file', function() + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + cli:set_name('myapp') + local args, err = cli:parse({ '--config-file=spec/.hidden/.busted_empty' }) + assert.is_nil(args) + assert.is_equal('myapp: error: .busted file does not return a table.', err) + end) + + it('detects unknown/invalid task', function() + local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + cli:set_name('appname') + local args, err = cli:parse({ '--config-file=spec/.hidden/.busted', '--run=invalid' }) + assert.is_nil(args) + assert.is_equal('appname: error: Task `invalid` not found, or not a table.', err) + end) end) describe('Tests command-line parse errors', function() diff --git a/spec/modules/configuration_loader_spec.lua b/spec/modules/configuration_loader_spec.lua index 104e0bc0..d25f18c3 100644 --- a/spec/modules/configuration_loader_spec.lua +++ b/spec/modules/configuration_loader_spec.lua @@ -73,12 +73,14 @@ describe('Config Loader', function() it('returns an error with an invalid config', function() local config, err = configLoader('invalid', cliArgs) - assert.are_not.equal(nil, err) + assert.is_nil(config) + assert.are.equal('.busted file does not return a table.', err) end) it('returns an error with an invalid run', function() cliArgs.run = 'invalid' local config, err = configLoader(testConfig, cliArgs) - assert.are_not.equal(nil, err) + assert.is_nil(config) + assert.are.equal('Task `invalid` not found, or not a table.', err) end) end) From 413f9947e1f7671ec4550e9372ef0306e80d2801 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 29 Feb 2016 13:01:58 -0800 Subject: [PATCH 265/293] Fix bad escape sequence This fixes a bad escape sequence used in spec/modules/cli_spec.lua. Should be using '%' as the escape character instead of '\'. However, in order to be compatible with Lua 5.3, remove the parens from the match string for the failing test. --- spec/modules/cli_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index ca1f4d34..68cd840d 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -462,7 +462,7 @@ describe('Tests using .busted tasks', function() assert.is_nil(args) assert.has_match('^app: error: spec/.hidden/.busted_bad:8: ', err) assert.has_match("'doesnotexist'", err) - assert.has_match("\(a nil value\)", err) + assert.has_match("a nil value", err) end) it('detects invalid configuration file', function() From a3701e761a9ad73794c1dd03075693231b74bd53 Mon Sep 17 00:00:00 2001 From: Ingo Struck Date: Fri, 11 Mar 2016 14:45:37 +0100 Subject: [PATCH 266/293] new travis infra as per moteus/lua-travis-example --- .travis.yml | 22 ++++---- .travis/platform.sh | 15 ++++++ .travis/setenv_lua.sh | 3 ++ .travis/setup_lua.sh | 122 ++++++++++++++++++++++++++++++++++++++++++ .travis_setup.sh | 45 ---------------- 5 files changed, 153 insertions(+), 54 deletions(-) create mode 100644 .travis/platform.sh create mode 100644 .travis/setenv_lua.sh create mode 100644 .travis/setup_lua.sh delete mode 100644 .travis_setup.sh diff --git a/.travis.yml b/.travis.yml index bf143ba7..c2125f70 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,23 @@ language: c env: - - LUA='Lua 5.1' - - LUA='Lua 5.2' - - LUA='Lua 5.3' - - LUA='LuaJIT 2.0' + global: + - LUAROCKS=2.3.0 + matrix: + - LUA=lua5.1 + - LUA=lua5.2 + - LUA=lua5.3 + - LUA=luajit + - LUA=luajit2.0 + - LUA=luajit2.1 before_install: - - bash .travis_setup.sh + - source .travis/setenv_lua.sh + - luarocks install luasec + - luarocks install moonscript install: - - sudo apt-get update -qq - - sudo luarocks install luasec - - sudo luarocks install moonscript - - sudo luarocks make busted-scm-0.rockspec + - luarocks make busted-scm-0.rockspec script: busted diff --git a/.travis/platform.sh b/.travis/platform.sh new file mode 100644 index 00000000..7259a7d6 --- /dev/null +++ b/.travis/platform.sh @@ -0,0 +1,15 @@ +if [ -z "${PLATFORM:-}" ]; then + PLATFORM=$TRAVIS_OS_NAME; +fi + +if [ "$PLATFORM" == "osx" ]; then + PLATFORM="macosx"; +fi + +if [ -z "$PLATFORM" ]; then + if [ "$(uname)" == "Linux" ]; then + PLATFORM="linux"; + else + PLATFORM="macosx"; + fi; +fi diff --git a/.travis/setenv_lua.sh b/.travis/setenv_lua.sh new file mode 100644 index 00000000..8d8c8255 --- /dev/null +++ b/.travis/setenv_lua.sh @@ -0,0 +1,3 @@ +export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/luarocks/bin +bash .travis/setup_lua.sh +eval `$HOME/.lua/luarocks path` diff --git a/.travis/setup_lua.sh b/.travis/setup_lua.sh new file mode 100644 index 00000000..6dcc0c6e --- /dev/null +++ b/.travis/setup_lua.sh @@ -0,0 +1,122 @@ +#! /bin/bash + +# A script for setting up environment for travis-ci testing. +# Sets up Lua and Luarocks. +# LUA must be "lua5.1", "lua5.2" or "luajit". +# luajit2.0 - master v2.0 +# luajit2.1 - master v2.1 + +set -eufo pipefail + +LUAJIT_VERSION="2.0.4" +LUAJIT_BASE="LuaJIT-$LUAJIT_VERSION" + +source .travis/platform.sh + +LUA_HOME_DIR=$TRAVIS_BUILD_DIR/install/lua + +LR_HOME_DIR=$TRAVIS_BUILD_DIR/install/luarocks + +mkdir $HOME/.lua + +LUAJIT="no" + +if [ "$PLATFORM" == "macosx" ]; then + if [ "$LUA" == "luajit" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.0" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.1" ]; then + LUAJIT="yes"; + fi; +elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then + LUAJIT="yes"; +fi + +mkdir -p "$LUA_HOME_DIR" + +if [ "$LUAJIT" == "yes" ]; then + + if [ "$LUA" == "luajit" ]; then + curl --location https://github.com/LuaJIT/LuaJIT/archive/v$LUAJIT_VERSION.tar.gz | tar xz; + else + git clone https://github.com/LuaJIT/LuaJIT.git $LUAJIT_BASE; + fi + + cd $LUAJIT_BASE + + if [ "$LUA" == "luajit2.1" ]; then + git checkout v2.1; + # force the INSTALL_TNAME to be luajit + perl -i -pe 's/INSTALL_TNAME=.+/INSTALL_TNAME= luajit/' Makefile + fi + + make && make install PREFIX="$LUA_HOME_DIR" + + ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/luajit + ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/lua; + +else + + if [ "$LUA" == "lua5.1" ]; then + curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz + cd lua-5.1.5; + elif [ "$LUA" == "lua5.2" ]; then + curl http://www.lua.org/ftp/lua-5.2.4.tar.gz | tar xz + cd lua-5.2.4; + elif [ "$LUA" == "lua5.3" ]; then + curl http://www.lua.org/ftp/lua-5.3.2.tar.gz | tar xz + cd lua-5.3.2; + fi + + # Build Lua without backwards compatibility for testing + perl -i -pe 's/-DLUA_COMPAT_(ALL|5_2)//' src/Makefile + make $PLATFORM + make INSTALL_TOP="$LUA_HOME_DIR" install; + + ln -s $LUA_HOME_DIR/bin/lua $HOME/.lua/lua + ln -s $LUA_HOME_DIR/bin/luac $HOME/.lua/luac; + +fi + +cd $TRAVIS_BUILD_DIR + +lua -v + +LUAROCKS_BASE=luarocks-$LUAROCKS + +curl --location http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz + +cd $LUAROCKS_BASE + +if [ "$LUA" == "luajit" ]; then + ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; +elif [ "$LUA" == "luajit2.0" ]; then + ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; +elif [ "$LUA" == "luajit2.1" ]; then + ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.1" --prefix="$LR_HOME_DIR"; +else + ./configure --with-lua="$LUA_HOME_DIR" --prefix="$LR_HOME_DIR" +fi + +make build && make install + +ln -s $LR_HOME_DIR/bin/luarocks $HOME/.lua/luarocks + +cd $TRAVIS_BUILD_DIR + +luarocks --version + +rm -rf $LUAROCKS_BASE + +if [ "$LUAJIT" == "yes" ]; then + rm -rf $LUAJIT_BASE; +elif [ "$LUA" == "lua5.1" ]; then + rm -rf lua-5.1.5; +elif [ "$LUA" == "lua5.2" ]; then + rm -rf lua-5.2.4; +elif [ "$LUA" == "lua5.3" ]; then + rm -rf lua-5.3.2; +fi diff --git a/.travis_setup.sh b/.travis_setup.sh deleted file mode 100644 index 3f6cbede..00000000 --- a/.travis_setup.sh +++ /dev/null @@ -1,45 +0,0 @@ -# A script for setting up environment for travis-ci testing. -# Sets up Lua and Luarocks. -# LUA must be "Lua 5.1", "Lua 5.2", "Lua 5.3" or "LuaJIT 2.0". - -set -e - -echo 'rocks_servers = { - "http://luarocks.org/manifests/olivine-labs", - "http://rocks.moonscript.org/", - "http://luarocks.org/repositories/rocks", - "http://luarocks.logiceditor.com/rocks", - "http://liblua.so/luarocks/repositories/rocks" -}' >> ~/config.lua - - -if [ "$LUA" == "LuaJIT 2.0" ]; then - wget -O - http://luajit.org/download/LuaJIT-2.0.4.tar.gz | tar xz - cd LuaJIT-2.0.4 - make && sudo make install INSTALL_TSYMNAME=lua; -else - if [ "$LUA" == "Lua 5.1" ]; then - wget -O - http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz - cd lua-5.1.5; - elif [ "$LUA" == "Lua 5.2" ]; then - wget -O - http://www.lua.org/ftp/lua-5.2.4.tar.gz | tar xz - cd lua-5.2.4; - elif [ "$LUA" == "Lua 5.3" ]; then - wget -O - http://www.lua.org/ftp/lua-5.3.0.tar.gz | tar xz - cd lua-5.3.0; - fi - sudo make linux install; -fi - -cd .. -wget -O - http://luarocks.org/releases/luarocks-2.2.2.tar.gz | tar xz || wget -O - http://keplerproject.github.io/luarocks/releases/luarocks-2.2.2.tar.gz | tar xz -cd luarocks-2.2.2 - -if [ "$LUA" == "LuaJIT 2.0" ]; then - ./configure --with-lua-include=/usr/local/include/luajit-2.0; -else - ./configure; -fi - -make build && sudo make install -cd .. From 269bdd8457a2218f8d043a9760119237dd8a7e6c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 8 Apr 2016 13:48:15 -0700 Subject: [PATCH 267/293] Fix bash completion error This checks that the `_compopt_o_filenames` function exists before calling it. Otherwise, it just uses `compopt -o filenames` instead. --- completions/bash/busted.bash | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index 815f3960..d590ba21 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -37,7 +37,12 @@ _busted() { toks=( ${toks[@]-} $(compgen -f -X "!*.lua" -- ${cur} ) ) toks=( ${toks[@]-} $(compgen -f -X "!*.moon" -- ${cur} ) ) toks=( ${toks[@]-} $(compgen -d -- ${cur} ) ) - _compopt_o_filenames + + if declare -fF _compopt_o_filenames > /dev/null; then + _compopt_o_filenames + else + compopt -o filenames + fi COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" ) return 0 From b30cd6dfb27ceac07c4d4bf81f0f0005f8ab41e5 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 8 Apr 2016 14:51:44 -0700 Subject: [PATCH 268/293] Improve randomness by using /dev/urandom This also ensures that a different random seed is used when repeat is greater than 1 and a seed is not specified. If `/dev/urandom` is not available, then default to `os.time()`. --- busted/execute.lua | 26 +++++++++++++++++++++++--- busted/modules/cli.lua | 2 +- busted/modules/test_file_loader.lua | 7 ------- busted/runner.lua | 10 ++++++---- busted/utils.lua | 16 +++++++++++++--- spec/modules/cli_spec.lua | 6 +++--- 6 files changed, 46 insertions(+), 21 deletions(-) diff --git a/busted/execute.lua b/busted/execute.lua index 4f3bcf93..c78df978 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -1,11 +1,26 @@ +local shuffle = require 'busted.utils'.shuffle +local urandom = require 'busted.utils'.urandom +local tablex = require 'pl.tablex' + +local function sort(elements) + table.sort(elements, function(t1, t2) + if t1.name and t2.name then + return t1.name < t2.name + end + return t2.name ~= nil + end) + return elements +end return function(busted) local block = require 'busted.block'(busted) local function execute(runs, options) + local root = busted.context.get() + local children = tablex.copy(busted.context.children(root)) + local function suite_reset() local oldctx = busted.context.get() - local children = busted.context.children(oldctx) busted.context.clear() local ctx = busted.context.get() @@ -20,11 +35,10 @@ return function(busted) busted.context.attach(child) end - busted.randomseed = tonumber(options.seed) or os.time() + busted.randomseed = tonumber(options.seed) or urandom() or os.time() end for i = 1, runs do - local root = busted.context.get() local seed = (busted.randomize and busted.randomseed or nil) if i > 1 then @@ -33,6 +47,12 @@ return function(busted) busted.safe_publish('suite', { 'suite', 'reset' }, root, i, runs) end + if options.shuffle then + shuffle(busted.context.children(root), busted.randomseed) + elseif options.sort then + sort(busted.context.children(root)) + end + if busted.safe_publish('suite', { 'suite', 'start' }, root, i, runs, seed) then if block.setup(root) then busted.execute() diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 9e6ec6d9..7e6c66c0 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -15,7 +15,7 @@ return function(options) local defaultOutput = options.defaultOutput local defaultLoaders = 'lua,moonscript' local defaultPattern = '_spec' - local defaultSeed = 'os.time()' + local defaultSeed = '/dev/urandom or os.time()' local lpathprefix = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpathprefix = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 2f4b05b1..764ecbe3 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -4,7 +4,6 @@ return function(busted, loaders) local path = require 'pl.path' local dir = require 'pl.dir' local tablex = require 'pl.tablex' - local shuffle = require 'busted.utils'.shuffle local fileLoaders = {} for _, v in pairs(loaders) do @@ -59,12 +58,6 @@ return function(busted, loaders) local loadTestFiles = function(rootFiles, pattern, options) local fileList = getAllTestFiles(rootFiles, pattern, options) - if options.shuffle then - shuffle(fileList, options.seed) - elseif options.sort then - table.sort(fileList) - end - for i, fileName in ipairs(fileList) do local testFile, getTrace, rewriteMessage = loadTestFile(busted, fileName) diff --git a/busted/runner.lua b/busted/runner.lua index daccedf7..c09a61b5 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -119,7 +119,7 @@ return function(options) -- Set up randomization options busted.sort = cliArgs['sort-tests'] busted.randomize = cliArgs['shuffle-tests'] - busted.randomseed = tonumber(cliArgs.seed) or os.time() + busted.randomseed = tonumber(cliArgs.seed) or utils.urandom() or os.time() -- Set up output handler to listen to events outputHandlerLoader(busted, cliArgs.output, { @@ -157,8 +157,6 @@ return function(options) local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) testFileLoader(rootFiles, pattern, { verbose = cliArgs.verbose, - sort = cliArgs['sort-files'], - shuffle = cliArgs['shuffle-files'], recursive = cliArgs['recursive'], seed = busted.randomseed }) @@ -173,7 +171,11 @@ return function(options) local runs = cliArgs['repeat'] local execute = require 'busted.execute'(busted) - execute(runs, { seed = cliArgs.seed }) + execute(runs, { + seed = cliArgs.seed, + shuffle = cliArgs['shuffle-files'], + sort = cliArgs['sort-files'], + }) busted.publish({ 'exit' }) diff --git a/busted/utils.lua b/busted/utils.lua index b682532f..75f4b5d9 100644 --- a/busted/utils.lua +++ b/busted/utils.lua @@ -1,5 +1,3 @@ -math.randomseed(os.time()) - return { split = require 'pl.utils'.split, @@ -12,5 +10,17 @@ return { n = n - 1 end return t - end + end, + + urandom = function() + local f = io.open('/dev/urandom', 'rb') + if not f then return nil end + local s = f:read(4) f:close() + local bytes = {s:byte(1, 4)} + local value = 0 + for _, v in ipairs(bytes) do + value = value * 256 + v + end + return value + end, } diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 68cd840d..8f2cd5f2 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -15,7 +15,7 @@ describe('Tests command-line interface', function() assert.is_equal('./', args.directory) assert.is_equal('_spec', args.p) assert.is_equal('_spec', args.pattern) - assert.is_equal('os.time()', args.seed) + assert.is_equal('/dev/urandom or os.time()', args.seed) assert.is_equal('en', args.lang) assert.is_equal(1, args['repeat']) assert.is_equal(lpath, args.m) @@ -330,7 +330,7 @@ describe('Tests using .busted tasks', function() assert.is_equal(normpath('spec/.hidden'), args.directory) assert.is_equal('_spec', args.p) assert.is_equal('_spec%.lua$', args.pattern) - assert.is_equal('os.time()', args.seed) + assert.is_equal('/dev/urandom or os.time()', args.seed) assert.is_equal('en', args.lang) assert.is_equal(1, args['repeat']) assert.is_equal(lpath, args.m) @@ -390,7 +390,7 @@ describe('Tests using .busted tasks', function() assert.is_equal('spec/.hidden/.busted', args['config-file']) assert.is_equal('_spec', args.p) assert.is_equal('_spec%.lua$', args.pattern) - assert.is_equal('os.time()', args.seed) + assert.is_equal('/dev/urandom or os.time()', args.seed) assert.is_equal('en', args.lang) assert.is_equal(1, args['repeat']) assert.is_equal(lpath, args.m) From d4431f27689549cc79d433cd7c905ca05c87642c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 9 Apr 2016 23:12:25 -0700 Subject: [PATCH 269/293] Export children to busted public api This exports the `children` function to the busted public API, returning a list of children for the specified context, making it symmetric to the `parent` function. --- busted/init.lua | 1 + spec/export_spec.lua | 1 + 2 files changed, 2 insertions(+) diff --git a/busted/init.lua b/busted/init.lua index f472dd3c..31982aad 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -107,6 +107,7 @@ local function init(busted) busted.exportApi('fail', busted.fail) busted.exportApi('gettime', busted.gettime) busted.exportApi('parent', busted.context.parent) + busted.exportApi('children', busted.context.children) busted.exportApi('sleep', busted.sleep) busted.exportApi('version', busted.version) diff --git a/spec/export_spec.lua b/spec/export_spec.lua index 116f059c..330a1522 100644 --- a/spec/export_spec.lua +++ b/spec/export_spec.lua @@ -76,6 +76,7 @@ describe('tests require "busted"', function() assert.is_function(require 'busted'.fail) assert.is_function(require 'busted'.gettime) assert.is_function(require 'busted'.parent) + assert.is_function(require 'busted'.children) assert.is_function(require 'busted'.sleep) assert.is_string(require 'busted'.version) end) From db6a4cf238671cd08b169f750529efa95b0c3cce Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 10 Apr 2016 00:24:05 -0700 Subject: [PATCH 270/293] Fixes for Windows --- busted-2.0.rc11-0.rockspec | 2 +- busted-scm-0.rockspec | 2 +- spec/cl_spec.lua | 5 +++-- spec/lua.bat | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 spec/lua.bat diff --git a/busted-2.0.rc11-0.rockspec b/busted-2.0.rc11-0.rockspec index c66031a7..75e53450 100644 --- a/busted-2.0.rc11-0.rockspec +++ b/busted-2.0.rc11-0.rockspec @@ -21,7 +21,7 @@ dependencies = { 'lua >= 5.1', 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', - 'luasystem >= 0.1.0-0', + 'luasystem >= 0.1.1-0', 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.8-0', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 5a5d95b3..651eeb29 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -21,7 +21,7 @@ dependencies = { 'lua >= 5.1', 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', - 'luasystem >= 0.1.0-0', + 'luasystem >= 0.1.1-0', 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.8-0', diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 4299a69c..bdad8fb3 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -213,10 +213,11 @@ describe('Tests the busted command-line options', function() end) it('can switch interpreters', function() - local success, errcnt, out = executeBusted('--lua=spec/lua.lua spec/cl_success.lua') + local lua_exe = normpath(path.is_windows and 'spec/lua.bat' or 'spec/lua.lua') + local success, errcnt, out = executeBusted('--lua=' .. lua_exe .. ' spec/cl_success.lua') assert.is_true(success) assert.is_equal(0, errcnt) - assert.equal('bin/busted --ignore-lua --lua=spec/lua.lua spec/cl_success.lua\n', out) + assert.equal('bin/busted --ignore-lua --lua=' .. lua_exe .. ' spec/cl_success.lua\n', out) end) end) diff --git a/spec/lua.bat b/spec/lua.bat new file mode 100644 index 00000000..d347ee38 --- /dev/null +++ b/spec/lua.bat @@ -0,0 +1,2 @@ +@echo off +lua "%~dp0\lua.lua" %* From 909e49d0d274b049eb84d41e79db6d55bf5c7175 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 27 Apr 2016 16:46:06 -0700 Subject: [PATCH 271/293] Make test file order deterministic This updates the test file loader to sort each group of test files it finds, preserving the order of any tests specified on the command-line. As a result, the order of test files will be deterministic and will not depend on the order that the files occur on the filesystem. This also makes shuffling test files reproducible across different systems when specifying the same random seed, assuming the version of Lua across these systems uses the same random number generator. --- busted/modules/test_file_loader.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 764ecbe3..72913e32 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -35,6 +35,7 @@ return function(busted, loaders) fileList = {} end + table.sort(fileList) return fileList end From f36259a31645fc55bab06d9c358d952233bad3de Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 27 Apr 2016 10:54:28 -0700 Subject: [PATCH 272/293] Fix the random seed sent to suite start The random seed being sent to suite start is incorrect when multiple runs are requested. In such cases, the seed passed to suite start is actually the seed for the previous run and not the current run. This change passes to suite start the random seed being used for the current run. --- busted/execute.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/busted/execute.lua b/busted/execute.lua index c78df978..7543bf38 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -39,8 +39,6 @@ return function(busted) end for i = 1, runs do - local seed = (busted.randomize and busted.randomseed or nil) - if i > 1 then suite_reset() root = busted.context.get() @@ -53,6 +51,7 @@ return function(busted) sort(busted.context.children(root)) end + local seed = (busted.randomize and busted.randomseed or nil) if busted.safe_publish('suite', { 'suite', 'start' }, root, i, runs, seed) then if block.setup(root) then busted.execute() From fcecf44d13a68856b61094190459810295e68c91 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 2 May 2016 23:21:48 -0700 Subject: [PATCH 273/293] Remove unused parameter --- busted/runner.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/busted/runner.lua b/busted/runner.lua index c09a61b5..4ce50beb 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -158,7 +158,6 @@ return function(options) testFileLoader(rootFiles, pattern, { verbose = cliArgs.verbose, recursive = cliArgs['recursive'], - seed = busted.randomseed }) -- If running standalone, setup test file to be compatible with live coding From 75ed36b5c1c627e29ca2ecf5305caac41343136a Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 2 May 2016 23:25:17 -0700 Subject: [PATCH 274/293] Set the root context randomseed key This sets the root context's randomseed key when shuffling test files is enabled, matching the way a file or describe context block sets the randomseed key. --- busted/execute.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/busted/execute.lua b/busted/execute.lua index 7543bf38..f940cf06 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -46,6 +46,7 @@ return function(busted) end if options.shuffle then + root.randomseed = busted.randomseed shuffle(busted.context.children(root), busted.randomseed) elseif options.sort then sort(busted.context.children(root)) From 9d1afd40b0255aa9b7fe9624f5f8d9f200341f4e Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 2 May 2016 23:22:21 -0700 Subject: [PATCH 275/293] Color randomizing note in gtest output handler This matches the color (yellow) used in gtest to display the randomizing note with the random seed when randomization is enabled. --- busted/outputHandlers/gtest.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index 5a09b6ae..b672afa2 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -18,7 +18,7 @@ return function(options) local handler = require 'busted.outputHandlers.base'() local repeatSuiteString = '\nRepeating all tests (run %d of %d) . . .\n\n' - local randomizeString = 'Note: Randomizing test order with a seed of %d.\n' + local randomizeString = colors.yellow('Note: Randomizing test order with a seed of %d.\n') local suiteStartString = colors.green ('[==========]') .. ' Running tests from scanned files.\n' local globalSetup = colors.green ('[----------]') .. ' Global test environment setup.\n' local fileStartString = colors.green ('[----------]') .. ' Running tests from %s\n' From 7f65b72fb1c078c9b00f4d98889766753347a191 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Tue, 3 May 2016 00:20:38 -0700 Subject: [PATCH 276/293] Support optional seed parameter to randomize() Add support for an optional random seed parameter to be specified to the `randomize()` function. --- busted/block.lua | 8 ++++-- busted/outputHandlers/gtest.lua | 8 +++--- spec/randomize_spec.lua | 43 +++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/busted/block.lua b/busted/block.lua index 49e50c44..4eca1d91 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -135,14 +135,18 @@ return function(busted) if not element.env then element.env = {} end local randomize = busted.randomize + local randomseed = busted.randomseed element.env.randomize = function(...) randomize = (select('#', ...) == 0 or ...) + if randomize then + randomseed = tonumber(({...})[1]) or tonumber(({...})[2]) or randomseed + end end if busted.safe(descriptor, element.run, element):success() then if randomize then - element.randomseed = busted.randomseed - shuffle(busted.context.children(element), busted.randomseed) + element.randomseed = randomseed + shuffle(busted.context.children(element), randomseed) elseif busted.sort then sort(busted.context.children(element)) end diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index b672afa2..dd246b8b 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -74,13 +74,13 @@ return function(options) end local failureDescription = function(failure) - local string + local string = failure.randomseed and ('Random seed: ' .. failure.randomseed .. '\n') or '' if type(failure.message) == 'string' then - string = failure.message + string = string .. failure.message elseif failure.message == nil then - string = 'Nil error' + string = string .. 'Nil error' else - string = pretty.write(failure.message) + string = string .. pretty.write(failure.message) end string = string .. '\n' diff --git a/spec/randomize_spec.lua b/spec/randomize_spec.lua index 2b78d22c..d3b8d76c 100644 --- a/spec/randomize_spec.lua +++ b/spec/randomize_spec.lua @@ -1,5 +1,7 @@ local unexpected = {} local order = {} +local orderfixed1 = {} +local orderfixed2 = {} describe('Randomizing test order', function() randomize() @@ -13,10 +15,51 @@ describe('Randomizing test order', function() end end) +describe('Randomizing test order with fixed seed as first arg', function() + randomize(3210) + + for i = 1, 10 do + it('does 10 its', function() + table.insert(orderfixed1, i) + end) + end +end) + +describe('Randomizing test order with fixed seed as second arg', function() + randomize(true, 56789) + + for i = 1, 10 do + it('does 10 its', function() + table.insert(orderfixed2, i) + end) + end +end) + describe('Order of tests ran', function() + local function shuffle(t, seed) + math.randomseed(seed) + local n = #t + while n >= 1 do + local k = math.random(n) + t[n], t[k] = t[k], t[n] + n = n - 1 + end + return t + end + it('randomized', function() assert.are_not.same(unexpected, order) end) + + it('randomized with known random seed: 3210', function() + local t = {1,2,3,4,5,6,7,8,9,10} + assert.are.same(shuffle(t, 3210), orderfixed1) + end) + + it('randomized with known random seed: 56789', function() + local t = {1,2,3,4,5,6,7,8,9,10} + assert.are.same(shuffle(t, 56789), orderfixed2) + end) end) describe('Disabling randomized test order with randomize(false)', function() From 0796e7fd1cc942da1a14152b3c1e945fd8c442d9 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 21 Apr 2016 00:39:22 -0700 Subject: [PATCH 277/293] Allow multiple occurrences of `--pattern` option This allows the user to specify multiple `--pattern` command-line options, and updates the busted task file to allow for specifying patterns as a single string (for a single pattern) or as a list of strings (for multiple patterns). --- busted/modules/cli.lua | 13 ++++++++- busted/modules/test_file_loader.lua | 22 ++++++++++----- busted/runner.lua | 4 +-- spec/.hidden/.busted | 6 ++++- spec/modules/cli_spec.lua | 42 ++++++++++++++++------------- 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 7e6c66c0..7e4d01dc 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -21,6 +21,10 @@ return function(options) local cliArgsParsed = {} + local function makeList(values) + return type(values) == 'table' and values or { values } + end + local function fixupList(values, sep) local sep = sep or ',' local list = type(values) == 'table' and values or { values } @@ -113,7 +117,7 @@ return function(options) if not options.standalone then cli:splat('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 999, processArgList) - cli:option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processOption) + cli:option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processMultiOption) end cli:option('-e STATEMENT', 'execute statement STATEMENT', nil, processMultiOption) @@ -188,6 +192,13 @@ return function(options) exit(code) end + -- Ensure multi-options are in a list + cliArgs.e = makeList(cliArgs.e) + cliArgs.pattern = makeList(cliArgs.pattern) + cliArgs.p = cliArgs.pattern + cliArgs.filter = makeList(cliArgs.filter) + cliArgs['filter-out'] = makeList(cliArgs['filter-out']) + -- Fixup options in case options from config file are not of the right form cliArgs.tags = fixupList(cliArgs.tags) cliArgs.t = cliArgs.tags diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 72913e32..8c841038 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -11,7 +11,7 @@ return function(busted, loaders) fileLoaders[#fileLoaders+1] = loader end - local getTestFiles = function(rootFile, pattern, options) + local getTestFiles = function(rootFile, patterns, options) local fileList if path.isfile(rootFile) then @@ -21,7 +21,13 @@ return function(busted, loaders) fileList = getfiles(rootFile) fileList = tablex.filter(fileList, function(filename) - return path.basename(filename):find(pattern or '') + local basename = path.basename(filename) + for _, patt in ipairs(patterns) do + if basename:find(patt) then + return true + end + end + return #patterns == 0 end) fileList = tablex.filter(fileList, function(filename) @@ -39,10 +45,10 @@ return function(busted, loaders) return fileList end - local getAllTestFiles = function(rootFiles, pattern, options) + local getAllTestFiles = function(rootFiles, patterns, options) local fileList = {} for _, root in ipairs(rootFiles) do - tablex.insertvalues(fileList, getTestFiles(root, pattern, options)) + tablex.insertvalues(fileList, getTestFiles(root, patterns, options)) end return fileList end @@ -56,8 +62,8 @@ return function(busted, loaders) end end - local loadTestFiles = function(rootFiles, pattern, options) - local fileList = getAllTestFiles(rootFiles, pattern, options) + local loadTestFiles = function(rootFiles, patterns, options) + local fileList = getAllTestFiles(rootFiles, patterns, options) for i, fileName in ipairs(fileList) do local testFile, getTrace, rewriteMessage = loadTestFile(busted, fileName) @@ -75,6 +81,10 @@ return function(busted, loaders) end if #fileList == 0 then + local pattern = patterns[1] + if #patterns > 1 then + pattern = '\n\t' .. table.concat(patterns, '\n\t') + end busted.publish({ 'error' }, {}, nil, s('output.no_test_files_match'):format(pattern), {}) end diff --git a/busted/runner.lua b/busted/runner.lua index 4ce50beb..dba129e2 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -153,9 +153,9 @@ return function(options) -- Load test directory local rootFiles = cliArgs.ROOT or { fileName } - local pattern = cliArgs.pattern + local patterns = cliArgs.pattern local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) - testFileLoader(rootFiles, pattern, { + testFileLoader(rootFiles, patterns, { verbose = cliArgs.verbose, recursive = cliArgs['recursive'], }) diff --git a/spec/.hidden/.busted b/spec/.hidden/.busted index 7ec40b31..96c4bc14 100644 --- a/spec/.hidden/.busted +++ b/spec/.hidden/.busted @@ -7,6 +7,8 @@ return { ['tags'] = {'tag11','tag22','tag33'}, ['exclude-tags'] = {'etag11','etag22','etag33'}, ['pattern'] = '_spec%.lua$', + ['filter'] = 'filt', + ['filter-out'] = 'filt-out', ['loaders'] = 'terra,moonscript', ['Xoutput'] = '-f,--flag', ['Xhelper'] = '-v,--verbose', @@ -14,7 +16,9 @@ return { test = { ['tags'] = 'test1,test2,test3', ['exclude-tags'] = 'etest1,etest2,etest3', - ['pattern'] = '_test%.lua$', + ['pattern'] = {'_test1%.lua$', '_test2%.lua$'}, + ['filter'] = {'filt1', 'filt2'}, + ['filter-out'] = {'filt1-out', 'filt2-out'}, ['loaders'] = {'lua','terra'}, ['Xoutput'] = {'-s','--sound'}, ['Xhelper'] = {'-t','--print'}, diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index 8f2cd5f2..af1da024 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -13,8 +13,6 @@ describe('Tests command-line interface', function() assert.is_same({'spec'}, args.ROOT) assert.is_equal('./', args.C) assert.is_equal('./', args.directory) - assert.is_equal('_spec', args.p) - assert.is_equal('_spec', args.pattern) assert.is_equal('/dev/urandom or os.time()', args.seed) assert.is_equal('en', args.lang) assert.is_equal(1, args['repeat']) @@ -38,7 +36,6 @@ describe('Tests command-line interface', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) - assert.is_nil(args.e) assert.is_nil(args.f) assert.is_nil(args['config-file']) assert.is_nil(args.shuffle) @@ -50,6 +47,9 @@ describe('Tests command-line interface', function() assert.is_nil(args.r) assert.is_nil(args.run) assert.is_nil(args.helper) + assert.is_same({}, args.e) + assert.is_same({'_spec'}, args.p) + assert.is_same({'_spec'}, args.pattern) assert.is_same({}, args.t) assert.is_same({}, args.tags) assert.is_same({}, args['exclude-tags']) @@ -64,8 +64,8 @@ describe('Tests command-line interface', function() local cli = require 'busted.modules.cli'({ standalone = true }) local args = cli:parse({}) assert.is_nil(args.ROOT) - assert.is_nil(args.p) - assert.is_nil(args.pattern) + assert.is_same({}, args.p) + assert.is_same({}, args.pattern) end) it('specify flags', function() @@ -202,8 +202,8 @@ describe('Tests command-line interface', function() local cli = require 'busted.modules.cli'({ standalone = false }) local args = cli:parse({ '-p', 'match_files', 'root_is_here' }) assert.is_same({'root_is_here'}, args.ROOT) - assert.is_equal('match_files', args.p) - assert.is_equal('match_files', args.pattern) + assert.is_same({'match_files'}, args.p) + assert.is_same({'match_files'}, args.pattern) end) it('specify multiple root paths', function() @@ -328,8 +328,6 @@ describe('Tests using .busted tasks', function() assert.is_same({'specs'}, args.ROOT) assert.is_equal(normpath('spec/.hidden'), args.C) assert.is_equal(normpath('spec/.hidden'), args.directory) - assert.is_equal('_spec', args.p) - assert.is_equal('_spec%.lua$', args.pattern) assert.is_equal('/dev/urandom or os.time()', args.seed) assert.is_equal('en', args.lang) assert.is_equal(1, args['repeat']) @@ -353,7 +351,6 @@ describe('Tests using .busted tasks', function() assert.is_false(args['enable-sound']) assert.is_false(args['suppress-pending']) assert.is_false(args['defer-print']) - assert.is_nil(args.e) assert.is_nil(args.f) assert.is_nil(args['config-file']) assert.is_nil(args.shuffle) @@ -365,11 +362,14 @@ describe('Tests using .busted tasks', function() assert.is_nil(args.r) assert.is_nil(args.run) assert.is_nil(args.helper) + assert.is_same({}, args.e) + assert.is_same({'_spec%.lua$'}, args.p) + assert.is_same({'_spec%.lua$'}, args.pattern) assert.is_same({'tag11', 'tag22', 'tag33'}, args.t) assert.is_same({'tag11', 'tag22', 'tag33'}, args.tags) assert.is_same({'etag11', 'etag22', 'etag33'}, args['exclude-tags']) - assert.is_same({}, args.filter) - assert.is_same({}, args['filter-out']) + assert.is_same({'filt'}, args.filter) + assert.is_same({'filt-out'}, args['filter-out']) assert.is_same({'-f', '--flag'}, args.Xoutput) assert.is_same({'-v', '--verbose'}, args.Xhelper) assert.is_same({'terra', 'moonscript'}, args.loaders) @@ -388,8 +388,6 @@ describe('Tests using .busted tasks', function() assert.is_equal('./', args.directory) assert.is_equal('spec/.hidden/.busted', args.f) assert.is_equal('spec/.hidden/.busted', args['config-file']) - assert.is_equal('_spec', args.p) - assert.is_equal('_spec%.lua$', args.pattern) assert.is_equal('/dev/urandom or os.time()', args.seed) assert.is_equal('en', args.lang) assert.is_equal(1, args['repeat']) @@ -422,11 +420,13 @@ describe('Tests using .busted tasks', function() assert.is_nil(args.r) assert.is_nil(args.run) assert.is_nil(args.helper) + assert.is_same({'_spec%.lua$'}, args.p) + assert.is_same({'_spec%.lua$'}, args.pattern) assert.is_same({'tag11', 'tag22', 'tag33'}, args.t) assert.is_same({'tag11', 'tag22', 'tag33'}, args.tags) assert.is_same({'etag11', 'etag22', 'etag33'}, args['exclude-tags']) - assert.is_same({}, args.filter) - assert.is_same({}, args['filter-out']) + assert.is_same({'filt'}, args.filter) + assert.is_same({'filt-out'}, args['filter-out']) assert.is_same({'-f', '--flag'}, args.Xoutput) assert.is_same({'-v', '--verbose'}, args.Xhelper) assert.is_same({'terra', 'moonscript'}, args.loaders) @@ -435,7 +435,9 @@ describe('Tests using .busted tasks', function() it('load configuration options', function() local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden', '--run=test' }) - assert.is_equal('_test%.lua$', args.pattern) + assert.is_same({'_test1%.lua$', '_test2%.lua$'}, args.pattern) + assert.is_same({'filt1', 'filt2'}, args.filter) + assert.is_same({'filt1-out', 'filt2-out'}, args['filter-out']) assert.is_same({'tests'}, args.ROOT) assert.is_same({'test1', 'test2', 'test3'}, args.tags) assert.is_same({'etest1', 'etest2', 'etest3'}, args['exclude-tags']) @@ -446,8 +448,10 @@ describe('Tests using .busted tasks', function() it('load configuration options and override with command-line', function() local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) - local args = cli:parse({ '--directory=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--loaders=moonscript' }) - assert.is_equal('patt', args.pattern) + local args = cli:parse({ '--directory=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--filter=fin', '--filter-out=fout', '--loaders=moonscript' }) + assert.is_same({'patt'}, args.pattern) + assert.is_same({'fin'}, args.filter) + assert.is_same({'fout'}, args['filter-out']) assert.is_same({'tag1'}, args.tags) assert.is_same({'etest1', 'etest2', 'etest3'}, args['exclude-tags']) assert.is_same({'-s','--sound'}, args.Xoutput) From 87961825eca2fced76ed7a2b9368ec81e05ddc54 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sun, 8 May 2016 02:01:12 -0700 Subject: [PATCH 278/293] Use monotime to measure time durations This avoids time reporting errors that may occur due to changes in the system time (i.e. when system time is modified by the user when a test is running). --- busted-2.0.rc11-0.rockspec | 2 +- busted-scm-0.rockspec | 2 +- busted/core.lua | 7 ++++++- busted/init.lua | 3 ++- busted/outputHandlers/base.lua | 6 ++++-- busted/outputHandlers/junit.lua | 8 ++++---- spec/export_spec.lua | 3 ++- 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/busted-2.0.rc11-0.rockspec b/busted-2.0.rc11-0.rockspec index 75e53450..67041335 100644 --- a/busted-2.0.rc11-0.rockspec +++ b/busted-2.0.rc11-0.rockspec @@ -21,7 +21,7 @@ dependencies = { 'lua >= 5.1', 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', - 'luasystem >= 0.1.1-0', + 'luasystem >= 0.2.0-0', 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.8-0', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index 651eeb29..f96e98ae 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -21,7 +21,7 @@ dependencies = { 'lua >= 5.1', 'lua_cliargs = 3.0-1', 'luafilesystem >= 1.5.0', - 'luasystem >= 0.1.1-0', + 'luasystem >= 0.2.0-0', 'dkjson >= 2.1.0', 'say >= 1.3-0', 'luassert >= 1.7.8-0', diff --git a/busted/core.lua b/busted/core.lua index 123f46f7..3b107f66 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -58,6 +58,7 @@ return function() local eattributes = {} busted.gettime = system.gettime + busted.monotime = system.monotime busted.sleep = system.sleep busted.status = require 'busted.status' @@ -209,10 +210,12 @@ return function() local args = {...} local n = select('#', ...) if channel[2] == 'start' then + element.starttick = busted.monotime() element.starttime = busted.gettime() elseif channel[2] == 'end' then element.endtime = busted.gettime() - element.duration = element.starttime and (element.endtime - element.starttime) + element.endtick = busted.monotime() + element.duration = element.starttick and (element.endtick - element.starttick) end local status = busted.safe(descriptor, function() busted.publish(channel, element, unpack(args, 1, n)) @@ -284,6 +287,8 @@ return function() name = name, run = fn, trace = trace, + starttick = nil, + endtick = nil, starttime = nil, endtime = nil, duration = nil, diff --git a/busted/init.lua b/busted/init.lua index 31982aad..c8e0ca8e 100644 --- a/busted/init.lua +++ b/busted/init.lua @@ -106,9 +106,10 @@ local function init(busted) busted.exportApi('bindfenv', busted.bindfenv) busted.exportApi('fail', busted.fail) busted.exportApi('gettime', busted.gettime) + busted.exportApi('monotime', busted.monotime) + busted.exportApi('sleep', busted.sleep) busted.exportApi('parent', busted.context.parent) busted.exportApi('children', busted.context.children) - busted.exportApi('sleep', busted.sleep) busted.exportApi('version', busted.version) busted.bindfenv(assert, 'error', busted.fail) diff --git a/busted/outputHandlers/base.lua b/busted/outputHandlers/base.lua index 0dc17a7f..7b6f5df1 100644 --- a/busted/outputHandlers/base.lua +++ b/busted/outputHandlers/base.lua @@ -75,14 +75,15 @@ return function() end handler.getDuration = function() - if not handler.endTime or not handler.startTime then + if not handler.endTick or not handler.startTick then return 0 end - return handler.endTime - handler.startTime + return handler.endTick - handler.startTick end handler.baseSuiteStart = function(suite) + handler.startTick = suite.starttick handler.startTime = suite.starttime return nil, true end @@ -102,6 +103,7 @@ return function() end handler.baseSuiteEnd = function(suite) + handler.endTick = suite.endtick handler.endTime = suite.endtime return nil, true end diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index 5d4408ad..ceafc289 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -5,7 +5,7 @@ return function(options) local busted = require 'busted' local handler = require 'busted.outputHandlers.base'() local top = { - start_time = busted.gettime(), + start_tick = busted.monotime(), xml_doc = xml.new('testsuites', { tests = 0, errors = 0, @@ -22,7 +22,7 @@ return function(options) handler.suiteStart = function(suite, count, total) local suite_xml = { - start_time = suite.starttime, + start_tick = suite.starttick, xml_doc = xml.new('testsuite', { name = 'Run ' .. count .. ' of ' .. total, tests = 0, @@ -44,7 +44,7 @@ return function(options) end local function elapsed(start_time) - return formatDuration(busted.gettime() - start_time) + return formatDuration(busted.monotime() - start_time) end handler.suiteEnd = function(suite, count, total) @@ -61,7 +61,7 @@ return function(options) end handler.exit = function() - top.xml_doc.attr.time = elapsed(top.start_time) + top.xml_doc.attr.time = elapsed(top.start_tick) local output_string = xml.tostring(top.xml_doc, '', '\t', nil, false) local file if 'string' == type(output_file_name) then diff --git a/spec/export_spec.lua b/spec/export_spec.lua index 330a1522..366ecad5 100644 --- a/spec/export_spec.lua +++ b/spec/export_spec.lua @@ -75,9 +75,10 @@ describe('tests require "busted"', function() assert.is_function(require 'busted'.bindfenv) assert.is_function(require 'busted'.fail) assert.is_function(require 'busted'.gettime) + assert.is_function(require 'busted'.monotime) + assert.is_function(require 'busted'.sleep) assert.is_function(require 'busted'.parent) assert.is_function(require 'busted'.children) - assert.is_function(require 'busted'.sleep) assert.is_string(require 'busted'.version) end) From 52cc01016dbb6a43510613663b0adf29291453d4 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Wed, 20 Apr 2016 22:32:27 -0700 Subject: [PATCH 279/293] Support --exclude-pattern command-line option Add support for specifying `--exclude-pattern` to exclude files matching the specified pattern from being run. This is analogous to the `--exclude-tags` and `--filter-out` command-line options. --- busted/modules/cli.lua | 2 ++ busted/modules/test_file_loader.lua | 5 +++++ busted/runner.lua | 1 + completions/bash/busted.bash | 4 ++-- completions/zsh/_busted | 1 + spec/.hidden/.busted | 2 ++ spec/cl_spec.lua | 20 ++++++++++++++++++++ spec/modules/cli_spec.lua | 15 ++++++++++++++- 8 files changed, 47 insertions(+), 3 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index 7e4d01dc..e2b4cfc8 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -118,6 +118,7 @@ return function(options) cli:splat('ROOT', 'test script file/folder. Folders will be traversed for any file that matches the --pattern option.', 'spec', 999, processArgList) cli:option('-p, --pattern=PATTERN', 'only run test files matching the Lua pattern', defaultPattern, processMultiOption) + cli:option('--exclude-pattern=PATTERN', 'do not run test files matching the Lua pattern, takes precedence over --pattern', nil, processMultiOption) end cli:option('-e STATEMENT', 'execute statement STATEMENT', nil, processMultiOption) @@ -196,6 +197,7 @@ return function(options) cliArgs.e = makeList(cliArgs.e) cliArgs.pattern = makeList(cliArgs.pattern) cliArgs.p = cliArgs.pattern + cliArgs['exclude-pattern'] = makeList(cliArgs['exclude-pattern']) cliArgs.filter = makeList(cliArgs.filter) cliArgs['filter-out'] = makeList(cliArgs['filter-out']) diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index 8c841038..a6b9b68b 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -22,6 +22,11 @@ return function(busted, loaders) fileList = tablex.filter(fileList, function(filename) local basename = path.basename(filename) + for _, patt in ipairs(options.excludes) do + if patt ~= '' and basename:find(patt) then + return nil + end + end for _, patt in ipairs(patterns) do if basename:find(patt) then return true diff --git a/busted/runner.lua b/busted/runner.lua index dba129e2..59529c95 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -156,6 +156,7 @@ return function(options) local patterns = cliArgs.pattern local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) testFileLoader(rootFiles, patterns, { + excludes = cliArgs['exclude-pattern'], verbose = cliArgs.verbose, recursive = cliArgs['recursive'], }) diff --git a/completions/bash/busted.bash b/completions/bash/busted.bash index d590ba21..fb2af435 100644 --- a/completions/bash/busted.bash +++ b/completions/bash/busted.bash @@ -128,7 +128,7 @@ _busted() { # no completion available return 0 ;; - -p|--pattern) + -p|--pattern|--exclude-pattern) # no completion available return 0 ;; @@ -165,7 +165,7 @@ _busted() { --version -l --list -o --output= - -p --pattern= + -p --pattern= --exclude-pattern= -C --directory= -f --config-file= -t --tags= --exclude-tags= diff --git a/completions/zsh/_busted b/completions/zsh/_busted index 13e77d10..8f100d16 100644 --- a/completions/zsh/_busted +++ b/completions/zsh/_busted @@ -49,6 +49,7 @@ _busted_args=( "(-m --lpath)"{-m,--lpath=}"[Optional path to be prefixed to the Lua module search path (default: ./src/?.lua;./src/?/?.lua;./src/?/init.lua)]:directory:_dirs" "(-o --output)"{-o,--output=}"[Output library to load (default: utfTerminal)]:output handlers:->output" "(-p --pattern)"{-p,--pattern=}"[Only run test files matching the Lua pattern (default: _spec)]: :" +"--exclude-pattern=[Do not run test files matching the Lua pattern, takes precedence over --pattern]: :" "(-r --run)"{-r,--run=}"[Config to run from .busted file]:run configurations:->run" "(-s --enable-sound)"{-s,--enable-sound}"[Executes 'say' command if available]" "(-t --tags)"{-t,--tags=}"[Only run tests with these #tags]: :" diff --git a/spec/.hidden/.busted b/spec/.hidden/.busted index 96c4bc14..4184008f 100644 --- a/spec/.hidden/.busted +++ b/spec/.hidden/.busted @@ -7,6 +7,7 @@ return { ['tags'] = {'tag11','tag22','tag33'}, ['exclude-tags'] = {'etag11','etag22','etag33'}, ['pattern'] = '_spec%.lua$', + ['exclude-pattern'] = '_exclude', ['filter'] = 'filt', ['filter-out'] = 'filt-out', ['loaders'] = 'terra,moonscript', @@ -17,6 +18,7 @@ return { ['tags'] = 'test1,test2,test3', ['exclude-tags'] = 'etest1,etest2,etest3', ['pattern'] = {'_test1%.lua$', '_test2%.lua$'}, + ['exclude-pattern'] = {'_exclude1', '_exclude2'}, ['filter'] = {'filt1', 'filt2'}, ['filter-out'] = {'filt1-out', 'filt2-out'}, ['loaders'] = {'lua','terra'}, diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index bdad8fb3..2bfa915c 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -80,6 +80,26 @@ describe('Tests the busted command-line options', function() assert.is_equal(1, errcnt) end) + it('tests running with --exclude-pattern specified', function () + local success, errcnt = executeBusted('--pattern="^cl_.*fail.*.lua$" --exclude-pattern="failing"') + assert.is_false(success) + assert.is_equal(4, errcnt) + end) + + it('tests running with --exclude-pattern="" disables exclude-pattern', function () + local success, errcnt = executeBusted('--pattern="cl_two_failures.lua$" --exclude-pattern ""') + assert.is_false(success) + assert.is_equal(2, errcnt) + local success, errcnt = executeBusted('--pattern="cl_success.lua$" --exclude-pattern=') + assert.is_true(success) + end) + + it('tests running with the same --pattern and --exclude-pattern specified', function () + local success, errcnt = executeBusted('--pattern="^cl_.*fail.*.lua$" --exclude-pattern="fail"') + assert.is_false(success) + assert.is_equal(1, errcnt) + end) + it('tests running with --filter specified', function () local success, errcnt = executeBusted('--pattern=_filter.lua$') assert.is_false(success) diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index af1da024..c8d6d0d7 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -50,6 +50,7 @@ describe('Tests command-line interface', function() assert.is_same({}, args.e) assert.is_same({'_spec'}, args.p) assert.is_same({'_spec'}, args.pattern) + assert.is_same({}, args['exclude-pattern']) assert.is_same({}, args.t) assert.is_same({}, args.tags) assert.is_same({}, args['exclude-tags']) @@ -66,6 +67,7 @@ describe('Tests command-line interface', function() assert.is_nil(args.ROOT) assert.is_same({}, args.p) assert.is_same({}, args.pattern) + assert.is_same({}, args['exclude-pattern']) end) it('specify flags', function() @@ -206,6 +208,13 @@ describe('Tests command-line interface', function() assert.is_same({'match_files'}, args.pattern) end) + it('specify ROOT arg and --exclude-pattern', function() + local cli = require 'busted.modules.cli'({ standalone = false }) + local args = cli:parse({ '--exclude-pattern', 'exclude_files', 'root_is_here' }) + assert.is_same({'root_is_here'}, args.ROOT) + assert.is_same({'exclude_files'}, args['exclude-pattern']) + end) + it('specify multiple root paths', function() local cli = require 'busted.modules.cli'({ standalone = false }) local args = cli:parse({'root1_path', 'root2_path', 'root3_path'}) @@ -365,6 +374,7 @@ describe('Tests using .busted tasks', function() assert.is_same({}, args.e) assert.is_same({'_spec%.lua$'}, args.p) assert.is_same({'_spec%.lua$'}, args.pattern) + assert.is_same({'_exclude'}, args['exclude-pattern']) assert.is_same({'tag11', 'tag22', 'tag33'}, args.t) assert.is_same({'tag11', 'tag22', 'tag33'}, args.tags) assert.is_same({'etag11', 'etag22', 'etag33'}, args['exclude-tags']) @@ -422,6 +432,7 @@ describe('Tests using .busted tasks', function() assert.is_nil(args.helper) assert.is_same({'_spec%.lua$'}, args.p) assert.is_same({'_spec%.lua$'}, args.pattern) + assert.is_same({'_exclude'}, args['exclude-pattern']) assert.is_same({'tag11', 'tag22', 'tag33'}, args.t) assert.is_same({'tag11', 'tag22', 'tag33'}, args.tags) assert.is_same({'etag11', 'etag22', 'etag33'}, args['exclude-tags']) @@ -436,6 +447,7 @@ describe('Tests using .busted tasks', function() local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden', '--run=test' }) assert.is_same({'_test1%.lua$', '_test2%.lua$'}, args.pattern) + assert.is_same({'_exclude1', '_exclude2'}, args['exclude-pattern']) assert.is_same({'filt1', 'filt2'}, args.filter) assert.is_same({'filt1-out', 'filt2-out'}, args['filter-out']) assert.is_same({'tests'}, args.ROOT) @@ -448,8 +460,9 @@ describe('Tests using .busted tasks', function() it('load configuration options and override with command-line', function() local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) - local args = cli:parse({ '--directory=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--filter=fin', '--filter-out=fout', '--loaders=moonscript' }) + local args = cli:parse({ '--directory=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--filter=fin', '--filter-out=fout', '--exclude-pattern', '', '--loaders=moonscript' }) assert.is_same({'patt'}, args.pattern) + assert.is_same({''}, args['exclude-pattern']) assert.is_same({'fin'}, args.filter) assert.is_same({'fout'}, args['filter-out']) assert.is_same({'tag1'}, args.tags) From 4f1199af09fbcba399f7ecf94e7f21b9edc3622d Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Sat, 14 May 2016 13:43:31 -0700 Subject: [PATCH 280/293] Fix TAP output handler for --suppress-pending option This fixes a bug in the TAP output handler causing busted to exit with an error when the `--suppress-pending` command-line option is used. --- busted/outputHandlers/TAP.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua index 311f1c14..72dc9c8f 100644 --- a/busted/outputHandlers/TAP.lua +++ b/busted/outputHandlers/TAP.lua @@ -77,8 +77,8 @@ return function(options) busted.subscribe({ 'suite', 'reset' }, handler.suiteReset) busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) - busted.subscribe({ 'test', 'start' }, handler.testStart) - busted.subscribe({ 'test', 'end' }, handler.testEnd) + busted.subscribe({ 'test', 'start' }, handler.testStart, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) busted.subscribe({ 'error' }, handler.error) return handler From 30a214330b1ec46a9cd36d41a7c6160e2ad3b187 Mon Sep 17 00:00:00 2001 From: "Jack Lawson ajacksified@gmail.com" Date: Tue, 24 May 2016 19:18:45 -0700 Subject: [PATCH 281/293] v2.0.rc12 --- busted-2.0.rc11-0.rockspec => busted-2.0.rc12-0.rockspec | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename busted-2.0.rc11-0.rockspec => busted-2.0.rc12-0.rockspec (100%) diff --git a/busted-2.0.rc11-0.rockspec b/busted-2.0.rc12-0.rockspec similarity index 100% rename from busted-2.0.rc11-0.rockspec rename to busted-2.0.rc12-0.rockspec From c3d96a51b724bd14d9d0a16fb97e74d95114c014 Mon Sep 17 00:00:00 2001 From: "Jack Lawson ajacksified@gmail.com" Date: Wed, 25 May 2016 08:22:26 -0700 Subject: [PATCH 282/293] Fix version mismatch in rockspec --- busted-2.0.rc12-0.rockspec => busted-2.0.rc12-1.rockspec | 6 +++--- busted/core.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename busted-2.0.rc12-0.rockspec => busted-2.0.rc12-1.rockspec (98%) diff --git a/busted-2.0.rc12-0.rockspec b/busted-2.0.rc12-1.rockspec similarity index 98% rename from busted-2.0.rc12-0.rockspec rename to busted-2.0.rc12-1.rockspec index 67041335..ca58a92d 100644 --- a/busted-2.0.rc12-0.rockspec +++ b/busted-2.0.rc12-1.rockspec @@ -1,8 +1,8 @@ package = 'busted' -version = '2.0.rc11-0' +version = '2.0.rc12-1' source = { - url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc11-0.tar.gz', - dir = 'busted-2.0.rc11-0' + url = 'https://github.com/Olivine-Labs/busted/archive/v2.0.rc12-1.tar.gz', + dir = 'busted-2.0.rc12-1' } description = { summary = 'Elegant Lua unit testing.', diff --git a/busted/core.lua b/busted/core.lua index 3b107f66..f9b869bf 100644 --- a/busted/core.lua +++ b/busted/core.lua @@ -45,7 +45,7 @@ return function() local mediator = require 'mediator'() local busted = {} - busted.version = '2.0.rc11-0' + busted.version = '2.0.rc12-0' local root = require 'busted.context'() busted.context = root.ref() From 72edf02e052f36eb01ece6de00fc232bb3022053 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 27 May 2016 22:18:25 -0700 Subject: [PATCH 283/293] Options --sort takes precedence over --shuffle --- busted/block.lua | 6 +++--- busted/execute.lua | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/busted/block.lua b/busted/block.lua index 4eca1d91..8ecc98ae 100644 --- a/busted/block.lua +++ b/busted/block.lua @@ -144,11 +144,11 @@ return function(busted) end if busted.safe(descriptor, element.run, element):success() then - if randomize then + if busted.sort then + sort(busted.context.children(element)) + elseif randomize then element.randomseed = randomseed shuffle(busted.context.children(element), randomseed) - elseif busted.sort then - sort(busted.context.children(element)) end if block.setup(element) then diff --git a/busted/execute.lua b/busted/execute.lua index f940cf06..8e0eea8c 100644 --- a/busted/execute.lua +++ b/busted/execute.lua @@ -45,11 +45,11 @@ return function(busted) busted.safe_publish('suite', { 'suite', 'reset' }, root, i, runs) end - if options.shuffle then + if options.sort then + sort(busted.context.children(root)) + elseif options.shuffle then root.randomseed = busted.randomseed shuffle(busted.context.children(root), busted.randomseed) - elseif options.sort then - sort(busted.context.children(root)) end local seed = (busted.randomize and busted.randomseed or nil) From 0dee22955c62207956030ac77e68efe1ab69e1f3 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 27 May 2016 22:51:19 -0700 Subject: [PATCH 284/293] Option --list honors --sort, --shuffle, --suppress-pending This updates the `--list` command-line option to honor `--sort`, `--shuffle`, and `--suppress-pending` flags. --- busted/modules/filter_loader.lua | 44 +++++++++++++++++++++++++------- busted/runner.lua | 19 +++++++------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/busted/modules/filter_loader.lua b/busted/modules/filter_loader.lua index 1d54b485..7154ff2a 100644 --- a/busted/modules/filter_loader.lua +++ b/busted/modules/filter_loader.lua @@ -55,11 +55,13 @@ return function() return nil, (#options.filter == 0) end - local printNameOnly = function(name, fn, trace) - local fullname = getFullName(name) - if trace and trace.what == 'Lua' then - print(trace.short_src .. ':' .. trace.currentline .. ': ' .. fullname) - else + local printTestName = function(element, parent, status) + if not (options.suppressPending and status == 'pending') then + local fullname = getFullName() + local trace = element.trace + if trace and trace.what == 'Lua' then + fullname = trace.short_src .. ':' .. trace.currentline .. ': ' .. fullname + end print(fullname) end return nil, false @@ -69,6 +71,15 @@ return function() return nil, false end + local noop = function() end + local stubOut = function(descriptor, name, fn, ...) + if fn == noop then + return nil, true + end + busted.publish({ 'register', descriptor }, name, noop, ...) + return nil, false + end + local skipOnError = function() return nil, not busted.skipAll end @@ -81,13 +92,28 @@ return function() end end + local applyDescFilter = function(descriptors, name, fn) + if options[name] and options[name] ~= '' then + for _, descriptor in ipairs(descriptors) do + local f = function(...) return fn(descriptor, ...) end + busted.subscribe({ 'register', descriptor }, f, { priority = 1 }) + end + end + end + if options.list then busted.subscribe({ 'suite', 'start' }, ignoreAll, { priority = 1 }) busted.subscribe({ 'suite', 'end' }, ignoreAll, { priority = 1 }) - applyFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'list', ignoreAll) - applyFilter({ 'lazy_setup', 'lazy_teardown' }, 'list', ignoreAll) - applyFilter({ 'strict_setup', 'strict_teardown' }, 'list', ignoreAll) - applyFilter({ 'it', 'pending' }, 'list', printNameOnly) + busted.subscribe({ 'file', 'start' }, ignoreAll, { priority = 1 }) + busted.subscribe({ 'file', 'end' }, ignoreAll, { priority = 1 }) + busted.subscribe({ 'describe', 'start' }, ignoreAll, { priority = 1 }) + busted.subscribe({ 'describe', 'end' }, ignoreAll, { priority = 1 }) + busted.subscribe({ 'test', 'start' }, ignoreAll, { priority = 1 }) + busted.subscribe({ 'test', 'end' }, printTestName, { priority = 1 }) + applyDescFilter({ 'setup', 'teardown', 'before_each', 'after_each' }, 'list', stubOut) + applyDescFilter({ 'lazy_setup', 'lazy_teardown' }, 'list', stubOut) + applyDescFilter({ 'strict_setup', 'strict_teardown' }, 'list', stubOut) + applyDescFilter({ 'it', 'pending' }, 'list', stubOut) end applyFilter({ 'lazy_setup', 'lazy_teardown' }, 'nokeepgoing', skipOnError) diff --git a/busted/runner.lua b/busted/runner.lua index 59529c95..2c9df674 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -132,6 +132,15 @@ return function(options) arguments = cliArgs.Xoutput, }) + -- Set up helper script + if cliArgs.helper and cliArgs.helper ~= '' then + helperLoader(busted, cliArgs.helper, { + verbose = cliArgs.verbose, + language = cliArgs.lang, + arguments = cliArgs.Xhelper + }) + end + -- Load tag and test filters filterLoader(busted, { tags = cliArgs.tags, @@ -140,17 +149,9 @@ return function(options) filterOut = cliArgs['filter-out'], list = cliArgs.list, nokeepgoing = not cliArgs['keep-going'], + suppressPending = cliArgs['suppress-pending'], }) - -- Set up helper script - if cliArgs.helper and cliArgs.helper ~= '' then - helperLoader(busted, cliArgs.helper, { - verbose = cliArgs.verbose, - language = cliArgs.lang, - arguments = cliArgs.Xhelper - }) - end - -- Load test directory local rootFiles = cliArgs.ROOT or { fileName } local patterns = cliArgs.pattern From aa6f4c92d9477630fffc2bc6b3f67226aabf3ed2 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Thu, 26 May 2016 13:47:55 -0700 Subject: [PATCH 285/293] Support running standalone tests from stdin This adds support for running standalone tests via stdin to the Lua interpreter. For example: lua < standalone_spec.lua or cat standalone_spec.lua | lua --- busted-2.0.rc12-1.rockspec | 1 + busted-scm-0.rockspec | 1 + busted/compatibility.lua | 4 +-- busted/modules/standalone_loader.lua | 28 ++++++++++++++++++ busted/runner.lua | 43 ++++++++++++++-------------- spec/cl_spec.lua | 6 ++++ 6 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 busted/modules/standalone_loader.lua diff --git a/busted-2.0.rc12-1.rockspec b/busted-2.0.rc12-1.rockspec index ca58a92d..5af0dfb4 100644 --- a/busted-2.0.rc12-1.rockspec +++ b/busted-2.0.rc12-1.rockspec @@ -48,6 +48,7 @@ build = { ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', ['busted.modules.luacov'] = 'busted/modules/luacov.lua', + ['busted.modules.standalone_loader'] = 'busted/modules/standalone_loader.lua', ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index f96e98ae..ff9a435a 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -48,6 +48,7 @@ build = { ['busted.modules.configuration_loader'] = 'busted/modules/configuration_loader.lua', ['busted.modules.luacov'] = 'busted/modules/luacov.lua', + ['busted.modules.standalone_loader'] = 'busted/modules/standalone_loader.lua', ['busted.modules.test_file_loader'] = 'busted/modules/test_file_loader.lua', ['busted.modules.output_handler_loader'] = 'busted/modules/output_handler_loader.lua', ['busted.modules.helper_loader'] = 'busted/modules/helper_loader.lua', diff --git a/busted/compatibility.lua b/busted/compatibility.lua index d8816a9a..39371ea6 100644 --- a/busted/compatibility.lua +++ b/busted/compatibility.lua @@ -33,8 +33,8 @@ return { loadstring = loadstring or load, unpack = table.unpack or unpack, - exit = function(code) - if code ~= 0 and _VERSION:match('^Lua 5%.[12]$') then + exit = function(code, force) + if not force and code ~= 0 and _VERSION:match('^Lua 5%.[12]$') then error() elseif code ~= 0 then code = 1 diff --git a/busted/modules/standalone_loader.lua b/busted/modules/standalone_loader.lua new file mode 100644 index 00000000..6299aa5f --- /dev/null +++ b/busted/modules/standalone_loader.lua @@ -0,0 +1,28 @@ +local getTrace = function(filename, info) + local index = info.traceback:find('\n%s*%[C]') + info.traceback = info.traceback:sub(1, index) + return info +end + +return function(busted) + local loadCurrentFile = function(info, options) + local filename = 'string' + if info.source:sub(1,1) == '@' or info.source:sub(1,1) == '=' then + filename = info.source:sub(2) + end + + -- Setup test file to be compatible with live coding + if info.func then + local file = setmetatable({ + getTrace = getTrace, + rewriteMessage = nil + }, { + __call = info.func + }) + + busted.executors.file(filename, file) + end + end + + return loadCurrentFile +end diff --git a/busted/runner.lua b/busted/runner.lua index 2c9df674..92c25246 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -29,28 +29,29 @@ return function(options) local level = 2 local info = debug.getinfo(level, 'Sf') local source = info.source - local fileName = source:sub(1,1) == '@' and source:sub(2) or source + local fileName = source:sub(1,1) == '@' and source:sub(2) or nil + local forceExit = fileName == nil -- Parse the cli arguments - local appName = path.basename(fileName) + local appName = path.basename(fileName or 'busted') cli:set_name(appName) local cliArgs, err = cli:parse(arg) if not cliArgs then io.stderr:write(err .. '\n') - exit(1) + exit(1, forceExit) end if cliArgs.version then -- Return early if asked for the version print(busted.version) - exit(0) + exit(0, forceExit) end -- Load current working directory local _, err = path.chdir(path.normpath(cliArgs.directory)) if err then io.stderr:write(appName .. ': error: ' .. err .. '\n') - exit(1) + exit(1, forceExit) end -- If coverage arg is passed in, load LuaCovsupport @@ -152,22 +153,20 @@ return function(options) suppressPending = cliArgs['suppress-pending'], }) - -- Load test directory - local rootFiles = cliArgs.ROOT or { fileName } - local patterns = cliArgs.pattern - local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) - testFileLoader(rootFiles, patterns, { - excludes = cliArgs['exclude-pattern'], - verbose = cliArgs.verbose, - recursive = cliArgs['recursive'], - }) - - -- If running standalone, setup test file to be compatible with live coding - if options.standalone then - local ctx = busted.context.get() - local children = busted.context.children(ctx) - local file = children[#children] - debug.getmetatable(file.run).__call = info.func + if cliArgs.ROOT then + -- Load test directories/files + local rootFiles = cliArgs.ROOT + local patterns = cliArgs.pattern + local testFileLoader = require 'busted.modules.test_file_loader'(busted, cliArgs.loaders) + testFileLoader(rootFiles, patterns, { + excludes = cliArgs['exclude-pattern'], + verbose = cliArgs.verbose, + recursive = cliArgs['recursive'], + }) + else + -- Running standalone, use standalone loader + local testFileLoader = require 'busted.modules.standalone_loader'(busted) + testFileLoader(info, { verbose = cliArgs.verbose }) end local runs = cliArgs['repeat'] @@ -181,6 +180,6 @@ return function(options) busted.publish({ 'exit' }) if options.standalone or failures > 0 or errors > 0 then - exit(failures + errors) + exit(failures + errors, forceExit) end end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 2bfa915c..36c15ecd 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -300,6 +300,12 @@ describe('Test busted running standalone', function() local success, errcnt = executeLua('spec/cl_standalone.lua --help') assert.is_false(success) end) + + it('tests running with via stdin', function() + local success, errcnt = executeLua('< spec/cl_standalone.lua') + assert.is_false(success) + assert.is_equal(3, errcnt) + end) end) describe('Test busted command-line runner', function() From 2734e084f9026a6c2672c5714075d8d63169eabf Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 27 May 2016 10:09:11 -0700 Subject: [PATCH 286/293] Rename output handler option for runner This renames the output handler option passed to `busted.runner` as `output` rather than `defaultOutput`. --- busted/modules/cli.lua | 2 +- busted/options.lua | 2 +- busted/runner.lua | 6 +++--- spec/modules/cli_spec.lua | 16 ++++++++-------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/busted/modules/cli.lua b/busted/modules/cli.lua index e2b4cfc8..cbc1a8bd 100644 --- a/busted/modules/cli.lua +++ b/busted/modules/cli.lua @@ -12,7 +12,7 @@ return function(options) local configLoader = require 'busted.modules.configuration_loader'() -- Default cli arg values - local defaultOutput = options.defaultOutput + local defaultOutput = options.output or 'utfTerminal' local defaultLoaders = 'lua,moonscript' local defaultPattern = '_spec' local defaultSeed = '/dev/urandom or os.time()' diff --git a/busted/options.lua b/busted/options.lua index a3b62bfa..c6f5d6cc 100644 --- a/busted/options.lua +++ b/busted/options.lua @@ -1,4 +1,4 @@ return { standalone = true, - defaultOutput = 'utfTerminal', + output = nil, } diff --git a/busted/runner.lua b/busted/runner.lua index 92c25246..d5d4d499 100644 --- a/busted/runner.lua +++ b/busted/runner.lua @@ -9,11 +9,11 @@ local loadstring = require 'busted.compatibility'.loadstring local loaded = false return function(options) - if loaded then return else loaded = true end + if loaded then return function() end else loaded = true end local isatty = io.type(io.stdout) == 'file' and term.isatty(io.stdout) options = tablex.update(require 'busted.options', options or {}) - options.defaultOutput = isatty and 'utfTerminal' or 'plainTerminal' + options.output = options.output or (isatty and 'utfTerminal' or 'plainTerminal') local busted = require 'busted.core'() @@ -124,7 +124,7 @@ return function(options) -- Set up output handler to listen to events outputHandlerLoader(busted, cliArgs.output, { - defaultOutput = options.defaultOutput, + defaultOutput = options.output, enableSound = cliArgs['enable-sound'], verbose = cliArgs.verbose, suppressPending = cliArgs['suppress-pending'], diff --git a/spec/modules/cli_spec.lua b/spec/modules/cli_spec.lua index c8d6d0d7..b70dfcb7 100644 --- a/spec/modules/cli_spec.lua +++ b/spec/modules/cli_spec.lua @@ -6,7 +6,7 @@ describe('Tests command-line interface', function() local defaultOutput = 'default_output_handler' local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) local args = cli:parse({}) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) @@ -330,7 +330,7 @@ describe('Tests using .busted tasks', function() local defaultOutput = 'default_output_handler' local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden' }) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) @@ -389,7 +389,7 @@ describe('Tests using .busted tasks', function() local defaultOutput = 'default_output_handler' local lpath = './src/?.lua;./src/?/?.lua;./src/?/init.lua' local cpath = path.is_windows and './csrc/?.dll;./csrc/?/?.dll;' or './csrc/?.so;./csrc/?/?.so;' - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) local args = cli:parse({ '--config-file', 'spec/.hidden/.busted' }) assert.is_equal(defaultOutput, args.o) assert.is_equal(defaultOutput, args.output) @@ -444,7 +444,7 @@ describe('Tests using .busted tasks', function() end) it('load configuration options', function() - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden', '--run=test' }) assert.is_same({'_test1%.lua$', '_test2%.lua$'}, args.pattern) assert.is_same({'_exclude1', '_exclude2'}, args['exclude-pattern']) @@ -459,7 +459,7 @@ describe('Tests using .busted tasks', function() end) it('load configuration options and override with command-line', function() - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) local args = cli:parse({ '--directory=spec/.hidden', '--run=test', '-t', 'tag1', '-p', 'patt', '--filter=fin', '--filter-out=fout', '--exclude-pattern', '', '--loaders=moonscript' }) assert.is_same({'patt'}, args.pattern) assert.is_same({''}, args['exclude-pattern']) @@ -473,7 +473,7 @@ describe('Tests using .busted tasks', function() end) it('detects error in configuration file', function() - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) cli:set_name('app') local args, err = cli:parse({ '--config-file=spec/.hidden/.busted_bad', '--run=test' }) assert.is_nil(args) @@ -483,7 +483,7 @@ describe('Tests using .busted tasks', function() end) it('detects invalid configuration file', function() - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) cli:set_name('myapp') local args, err = cli:parse({ '--config-file=spec/.hidden/.busted_empty' }) assert.is_nil(args) @@ -491,7 +491,7 @@ describe('Tests using .busted tasks', function() end) it('detects unknown/invalid task', function() - local cli = require 'busted.modules.cli'({ standalone = false, defaultOutput = defaultOutput }) + local cli = require 'busted.modules.cli'({ standalone = false, output = defaultOutput }) cli:set_name('appname') local args, err = cli:parse({ '--config-file=spec/.hidden/.busted', '--run=invalid' }) assert.is_nil(args) From 830f175c57ca3f9e79f95b8c4eaacf58252453d7 Mon Sep 17 00:00:00 2001 From: Chris Tallman Date: Fri, 10 Jun 2016 12:04:14 -0700 Subject: [PATCH 287/293] Fix testcase time --- busted/outputHandlers/junit.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/busted/outputHandlers/junit.lua b/busted/outputHandlers/junit.lua index ceafc289..f1d28a5f 100644 --- a/busted/outputHandlers/junit.lua +++ b/busted/outputHandlers/junit.lua @@ -101,7 +101,7 @@ return function(options) handler.testEnd = function(element, parent, status) top.xml_doc.attr.tests = top.xml_doc.attr.tests + 1 - testcase_node.time = formatDuration(element.duration) + testcase_node:set_attrib("time", formatDuration(element.duration)) if status == 'success' then testStatus(element, parent, nil, 'success') From 4e4df7a2bd7a8d52f4b09fa68fdaacbefda43d7f Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Fri, 15 Jul 2016 13:20:53 -0700 Subject: [PATCH 288/293] Use '%u' to format unsigned numbers This fixes a bug when trying to display an unsigned value using '%d', which will print a negative value when the value is too large. --- busted/outputHandlers/gtest.lua | 22 +++++++++++----------- busted/outputHandlers/plainTerminal.lua | 2 +- busted/outputHandlers/utfTerminal.lua | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/busted/outputHandlers/gtest.lua b/busted/outputHandlers/gtest.lua index dd246b8b..1b940a4f 100644 --- a/busted/outputHandlers/gtest.lua +++ b/busted/outputHandlers/gtest.lua @@ -17,8 +17,8 @@ return function(options) local busted = require 'busted' local handler = require 'busted.outputHandlers.base'() - local repeatSuiteString = '\nRepeating all tests (run %d of %d) . . .\n\n' - local randomizeString = colors.yellow('Note: Randomizing test order with a seed of %d.\n') + local repeatSuiteString = '\nRepeating all tests (run %u of %u) . . .\n\n' + local randomizeString = colors.yellow('Note: Randomizing test order with a seed of %u.\n') local suiteStartString = colors.green ('[==========]') .. ' Running tests from scanned files.\n' local globalSetup = colors.green ('[----------]') .. ' Global test environment setup.\n' local fileStartString = colors.green ('[----------]') .. ' Running tests from %s\n' @@ -27,28 +27,28 @@ return function(options) local skippedString = colors.yellow ('[ SKIPPED ]') .. ' %s (%.2f ms)\n' local failureString = colors.red ('[ FAILED ]') .. ' %s (%.2f ms)\n' local errorString = colors.magenta('[ ERROR ]') .. ' %s (%.2f ms)\n' - local fileEndString = colors.green ('[----------]') .. ' %d %s from %s (%.2f ms total)\n\n' + local fileEndString = colors.green ('[----------]') .. ' %u %s from %s (%.2f ms total)\n\n' local globalTeardown = colors.green ('[----------]') .. ' Global test environment teardown.\n' - local suiteEndString = colors.green ('[==========]') .. ' %d %s from %d test %s ran. (%.2f ms total)\n' - local successStatus = colors.green ('[ PASSED ]') .. ' %d %s.\n' + local suiteEndString = colors.green ('[==========]') .. ' %u %s from %u test %s ran. (%.2f ms total)\n' + local successStatus = colors.green ('[ PASSED ]') .. ' %u %s.\n' local summaryStrings = { skipped = { - header = colors.yellow ('[ SKIPPED ]') .. ' %d %s, listed below:\n', + header = colors.yellow ('[ SKIPPED ]') .. ' %u %s, listed below:\n', test = colors.yellow ('[ SKIPPED ]') .. ' %s\n', - footer = ' %d SKIPPED %s\n', + footer = ' %u SKIPPED %s\n', }, failure = { - header = colors.red ('[ FAILED ]') .. ' %d %s, listed below:\n', + header = colors.red ('[ FAILED ]') .. ' %u %s, listed below:\n', test = colors.red ('[ FAILED ]') .. ' %s\n', - footer = ' %d FAILED %s\n', + footer = ' %u FAILED %s\n', }, error = { - header = colors.magenta('[ ERROR ]') .. ' %d %s, listed below:\n', + header = colors.magenta('[ ERROR ]') .. ' %u %s, listed below:\n', test = colors.magenta('[ ERROR ]') .. ' %s\n', - footer = ' %d %s\n', + footer = ' %u %s\n', }, } diff --git a/busted/outputHandlers/plainTerminal.lua b/busted/outputHandlers/plainTerminal.lua index 1378b71d..e15f9879 100644 --- a/busted/outputHandlers/plainTerminal.lua +++ b/busted/outputHandlers/plainTerminal.lua @@ -130,7 +130,7 @@ return function(options) end handler.suiteStart = function(suite, count, total) - local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') + local runString = (total > 1 and '\nRepeating all tests (run %u of %u) . . .\n\n' or '') io.write(runString:format(count, total)) io.flush() diff --git a/busted/outputHandlers/utfTerminal.lua b/busted/outputHandlers/utfTerminal.lua index 3a2c0456..fa38c958 100644 --- a/busted/outputHandlers/utfTerminal.lua +++ b/busted/outputHandlers/utfTerminal.lua @@ -139,7 +139,7 @@ return function(options) end handler.suiteStart = function(suite, count, total) - local runString = (total > 1 and '\nRepeating all tests (run %d of %d) . . .\n\n' or '') + local runString = (total > 1 and '\nRepeating all tests (run %u of %u) . . .\n\n' or '') io.write(runString:format(count, total)) io.flush() From ed3f70805ac0e30bf14f6a5850e873329f5e337c Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 29 Aug 2016 11:54:59 -0700 Subject: [PATCH 289/293] Fix failing tests after penlight upgrade This fixes failing unit tests after upgrading `penlight`. Apparently, the new version of `penlight` uses `pl.List` internally when traversing a directory. Hence, we cannot use `pl.List` in any of the insulation tests. --- spec/insulate-expose_spec.lua | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/spec/insulate-expose_spec.lua b/spec/insulate-expose_spec.lua index 0409a3d1..bba84bd6 100644 --- a/spec/insulate-expose_spec.lua +++ b/spec/insulate-expose_spec.lua @@ -13,9 +13,9 @@ describe('Tests insulation', function() it('updates package.loaded', function() assert.is_not_nil(pl) - assert.is_not_nil(List) + assert.is_not_nil(Date) assert.is_not_nil(package.loaded.pl) - assert.is_not_nil(package.loaded['pl.List']) + assert.is_not_nil(package.loaded['pl.Date']) end) end) @@ -27,9 +27,9 @@ describe('Tests insulation', function() it('restores package.loaded', function() assert.is_nil(pl) - assert.is_nil(List) + assert.is_nil(Date) assert.is_nil(package.loaded.pl) - assert.is_nil(package.loaded['pl.List']) + assert.is_nil(package.loaded['pl.Date']) end) end) end) @@ -54,9 +54,9 @@ insulate('', function() it('updates package.loaded', function() assert.is_not_nil(pl) - assert.is_not_nil(List) + assert.is_not_nil(Date) assert.is_not_nil(package.loaded.pl) - assert.is_not_nil(package.loaded['pl.List']) + assert.is_not_nil(package.loaded['pl.Date']) end) end) end) @@ -74,9 +74,9 @@ insulate('', function() it('does not restore package.loaded', function() assert.is_not_nil(pl) - assert.is_not_nil(List) + assert.is_not_nil(Date) assert.is_not_nil(package.loaded.pl) - assert.is_not_nil(package.loaded['pl.List']) + assert.is_not_nil(package.loaded['pl.Date']) end) end) end) @@ -93,9 +93,9 @@ insulate('', function() end) it('Tests package.loaded persists without insulate', function() - assert.is_not_nil(List) + assert.is_not_nil(Date) assert.is_not_nil(package.loaded.pl) - assert.is_not_nil(package.loaded['pl.List']) + assert.is_not_nil(package.loaded['pl.Date']) end) end) @@ -107,9 +107,9 @@ describe('Tests after insulating an expose block', function() it('restores package.loaded', function() assert.is_nil(pl) - assert.is_nil(List) + assert.is_nil(Date) assert.is_nil(package.loaded.pl) - assert.is_nil(package.loaded['pl.List']) + assert.is_nil(package.loaded['pl.Date']) end) end) From 8ff1fc97d25d2ab1a6d49b03d8be556925c6c0a4 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 29 Aug 2016 11:01:04 -0700 Subject: [PATCH 290/293] Forward non-positive arg keys This updates the helper loader and output handler loader to forward non-positive command-line argument keys, that are automatically inserted by the Lua interpreter, to the helper and output handler, respectively. --- busted/modules/helper_loader.lua | 6 ++++-- busted/modules/output_handler_loader.lua | 2 ++ busted/utils.lua | 11 +++++++++++ spec/cl_spec.lua | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/busted/modules/helper_loader.lua b/busted/modules/helper_loader.lua index 693b903d..56ae6673 100644 --- a/busted/modules/helper_loader.lua +++ b/busted/modules/helper_loader.lua @@ -1,11 +1,13 @@ local path = require 'pl.path' local hasMoon, moonscript = pcall(require, 'moonscript') +local utils = require 'busted.utils' return function() local loadHelper = function(busted, helper, options) - local old_arg = arg + local old_arg = _G.arg local success, err = pcall(function() - arg = options.arguments + utils.copy_interpreter_args(options.arguments) + _G.arg = options.arguments if helper:match('%.lua$') then dofile(path.normpath(helper)) elseif hasMoon and helper:match('%.moon$') then diff --git a/busted/modules/output_handler_loader.lua b/busted/modules/output_handler_loader.lua index 41c45d4e..ab93e4c6 100644 --- a/busted/modules/output_handler_loader.lua +++ b/busted/modules/output_handler_loader.lua @@ -1,10 +1,12 @@ local path = require 'pl.path' local hasMoon, moonscript = pcall(require, 'moonscript') +local utils = require 'busted.utils' return function() local loadOutputHandler = function(busted, output, options) local handler + utils.copy_interpreter_args(options.arguments) local success, err = pcall(function() if output:match('%.lua$') then handler = dofile(path.normpath(output)) diff --git a/busted/utils.lua b/busted/utils.lua index 75f4b5d9..bf771487 100644 --- a/busted/utils.lua +++ b/busted/utils.lua @@ -1,4 +1,15 @@ return { + copy_interpreter_args = function(arguments) + -- copy non-positive command-line args auto-inserted by Lua interpreter + if arguments and _G.arg then + local i = 0 + while _G.arg[i] do + arguments[i] = _G.arg[i] + i = i - 1 + end + end + end, + split = require 'pl.utils'.split, shuffle = function(t, seed) diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 36c15ecd..46441421 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -301,7 +301,7 @@ describe('Test busted running standalone', function() assert.is_false(success) end) - it('tests running with via stdin', function() + it('tests running via stdin', function() local success, errcnt = executeLua('< spec/cl_standalone.lua') assert.is_false(success) assert.is_equal(3, errcnt) From b5060dd6f154807c152ee64e9919258c1728a7f8 Mon Sep 17 00:00:00 2001 From: Oscar Lim Date: Mon, 29 Aug 2016 10:11:03 -0700 Subject: [PATCH 291/293] Output error message when test file/dir not found Previously, if a test file or directory specified on the command-line is not found, the test file loader would silently fail without reporting an error. Hence, leading the user to think all requested tests were run, when, in fact, either an entire test file or directory was skipped. This updates the test file loader to report an error in the event a requested file or directory is not found. --- busted/languages/en.lua | 1 + busted/modules/test_file_loader.lua | 1 + spec/cl_spec.lua | 14 ++++++++++++++ 3 files changed, 16 insertions(+) diff --git a/busted/languages/en.lua b/busted/languages/en.lua index 285d1ba1..dcfb4cce 100644 --- a/busted/languages/en.lua +++ b/busted/languages/en.lua @@ -26,6 +26,7 @@ s:set('output.success_single', 'success') s:set('output.seconds', 'seconds') s:set('output.no_test_files_match', 'No test files found matching Lua pattern: %s') +s:set('output.file_not_found', 'Cannot find file or directory: %s') -- definitions following are not used within the 'say' namespace return { diff --git a/busted/modules/test_file_loader.lua b/busted/modules/test_file_loader.lua index a6b9b68b..6f2e83d8 100644 --- a/busted/modules/test_file_loader.lua +++ b/busted/modules/test_file_loader.lua @@ -43,6 +43,7 @@ return function(busted, loaders) end end) else + busted.publish({ 'error' }, {}, nil, s('output.file_not_found'):format(rootFile), {}) fileList = {} end diff --git a/spec/cl_spec.lua b/spec/cl_spec.lua index 36c15ecd..8fbf1e70 100644 --- a/spec/cl_spec.lua +++ b/spec/cl_spec.lua @@ -454,6 +454,20 @@ describe('Tests error messages through the command line', function() assert.is_equal(expectedMsg, errmsg) end) + it('when test file not found', function() + local _, _, result = executeBusted('--output=plainTerminal does_not_exist.lua') + local errmsg = result:match('Error %-> (.-)\n') + local expected = 'Cannot find file or directory: does_not_exist.lua' + assert.is_equal(expected, errmsg) + end) + + it('when test directory not found', function() + local _, _, result = executeBusted('--output=plainTerminal does_not_exist') + local errmsg = result:match('Error %-> (.-)\n') + local expected = 'Cannot find file or directory: does_not_exist' + assert.is_equal(expected, errmsg) + end) + it('when no test files matching Lua pattern', function() local _, _, result = executeBusted('--output=plainTerminal --pattern=this_filename_does_simply_not_exist$') local errmsg = result:match('Error %-> (.-)\n') From 907cd546e55597ad8fadc925fd16611f5564f132 Mon Sep 17 00:00:00 2001 From: Enea Scioni Date: Tue, 4 Oct 2016 16:20:59 +0200 Subject: [PATCH 292/293] add italian language support --- busted/languages/it.lua | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 busted/languages/it.lua diff --git a/busted/languages/it.lua b/busted/languages/it.lua new file mode 100644 index 00000000..a073bfe3 --- /dev/null +++ b/busted/languages/it.lua @@ -0,0 +1,50 @@ +local s = require('say') + +s:set_namespace('it') + +-- 'Pending: test.lua @ 12 \n description +s:set('output.pending', 'In attesa') +s:set('output.failure', 'Fallimento') +s:set('output.error', 'Errore') +s:set('output.success', 'Successo') + +s:set('output.pending_plural', 'in attesa') +s:set('output.failure_plural', 'fallimenti') +s:set('output.error_plural', 'errori') +s:set('output.success_plural', 'successi') + +s:set('output.pending_zero', 'in attesa') +s:set('output.failure_zero', 'fallimenti') +s:set('output.error_zero', 'errori') +s:set('output.success_zero', 'successi') + +s:set('output.pending_single', 'in attesa') +s:set('output.failure_single', 'fallimento') +s:set('output.error_single', 'errore') +s:set('output.success_single', 'successo') + +s:set('output.seconds', 'secondi') + +s:set('output.no_test_files_match', 'Nessun file di test trovat che corrisponde al pattern Lua: %s') +s:set('output.file_not_found', 'Nessun file o cartella trovato: %s') + +-- definitions following are not used within the 'say' namespace +return { + failure_messages = { + "Hai %d specifiche non conformi", + "Le tue specifiche non sono conformi", + "Il tuo codice fa schifo e dovresti sentirti male per questo", + "Il tuo codice è in pericolo", + "Strano. Il solo modo per terminare con successo i tuoi test è fare nessun test", + "Mia nonna ha scritto migliori specifiche su un 3 86", + "Ogni volta che trovi un errore, bevi un'altra birra", + "I fallimenti fanno male alla salute" + }, + success_messages = { + "Ma andiamo! Specifiche Ok!", + "Non importa, avevi le specifiche", + "Bella zio", + "Gran successo", + "Test passato, hai vinto una birra" + } +} From dcd49b0f57e52b46184b5df2b5e42f5cd855e9ee Mon Sep 17 00:00:00 2001 From: Enea Scioni Date: Tue, 4 Oct 2016 16:34:51 +0200 Subject: [PATCH 293/293] add it lang rockspec support --- busted-2.0.rc12-1.rockspec | 1 + busted-scm-0.rockspec | 1 + 2 files changed, 2 insertions(+) diff --git a/busted-2.0.rc12-1.rockspec b/busted-2.0.rc12-1.rockspec index 5af0dfb4..08d86dda 100644 --- a/busted-2.0.rc12-1.rockspec +++ b/busted-2.0.rc12-1.rockspec @@ -79,6 +79,7 @@ build = { ['busted.languages.th'] = 'busted/languages/th.lua', ['busted.languages.ua'] = 'busted/languages/ua.lua', ['busted.languages.zh'] = 'busted/languages/zh.lua', + ['busted.languages.it'] = 'busted/languages/it.lua', }, install = { bin = { diff --git a/busted-scm-0.rockspec b/busted-scm-0.rockspec index ff9a435a..4bb668f6 100644 --- a/busted-scm-0.rockspec +++ b/busted-scm-0.rockspec @@ -79,6 +79,7 @@ build = { ['busted.languages.th'] = 'busted/languages/th.lua', ['busted.languages.ua'] = 'busted/languages/ua.lua', ['busted.languages.zh'] = 'busted/languages/zh.lua', + ['busted.languages.it'] = 'busted/languages/it.lua', }, install = { bin = {