--- -- test_declare.lua -- -- Declare unit test suites, and fetch tests from them. -- -- Author Jason Perkins -- Copyright (c) 2008-2016 Jason Perkins and the Premake project. --- local p = premake local m = p.modules.self_test local _ = {} _.suites = {} _.suppressed = {} --- -- Declare a new test suite. -- -- @param suiteName -- A unique name for the suite. This name will be displayed as part of -- test failure messages, and also to select the suite when using the -- `--test-only` command line parameter. Best to avoid spaces and special -- characters which might not be command line friendly. An error will be -- raised if the name is not unique. -- @return -- The new test suite object. --- function m.declare(suiteName) if _.suites[suiteName] then error('Duplicate test suite "'.. suiteName .. '"', 2) end local _suite = {} -- Setup a metatable for the test suites to use, this will catch duplicate tests local suite = setmetatable({}, { __index = _suite, __newindex = function (table, key, value) if m.detectDuplicateTests and _suite[key] ~= nil then error('Duplicate test "'.. key .. '"', 2) end _suite[key] = value end, __pairs = function (table) return pairs(_suite) end, __ipairs = function (table) return ipairs(_suite) end, }) suite._SCRIPT_DIR = _SCRIPT_DIR suite._TESTS_DIR = _TESTS_DIR _.suites[suiteName] = suite return suite end --- -- Prevent a particular test or suite of tests from running. -- -- @param identifier -- A test or suite identifier, indicating which tests should be suppressed, -- in the form "suiteName" or "suiteName.testName". --- function m.suppress(identifier) if type(identifier) == "table" then for i = 1, #identifier do m.suppress(identifier[i]) end else _.suppressed[identifier] = true end end function m.isSuppressed(identifier) return _.suppressed[identifier] end --- -- Returns true if the provided test object represents a valid test. --- function m.isValid(test) if type(test.testFunction) ~= "function" then return false end if test.testName == "setup" or test.testName == "teardown" then return false end return true end --- -- Return the table of declared test suites. --- function m.getSuites() return _.suites end --- -- Fetch a test object via its string identifier. -- -- @param identifier -- An optional test or suite identifier, indicating which tests should be -- run, in the form "suiteName" or "suiteName.testName". If not specified, -- the global test object, representing all test suites, will be returned. -- @return -- On success, returns a test object, which should be considered opaque. -- On failure, returns `nil` and an error. --- function m.getTestWithIdentifier(identifier) local suiteName, testName = m.parseTestIdentifier(identifier) local suite, test, err = _.checkTestIdentifier(_.suites, suiteName, testName) if err then return nil, err end return { suiteName = suiteName, suite = suite, testName = testName, testFunction = test } end --- -- Parse a test identifier and split it into separate suite and test names. -- -- @param identifier -- A test identifier, which may be nil or an empty string, a test suite -- name, or a suite and test with the format "suiteName.testName". -- @return -- Two values: the suite name and the test name, or nil if not included -- in the identifier. --- function m.parseTestIdentifier(identifier) local suiteName, testName if identifier then local parts = string.explode(identifier, ".", true) suiteName = iif(parts[1] ~= "", parts[1], nil) testName = iif(parts[2] ~= "", parts[2], nil) end return suiteName, testName end function _.checkTestIdentifier(suites, suiteName, testName) local suite, test if suiteName then suite = suites[suiteName] if not suite then return nil, nil, "No such test suite '" .. suiteName .. "'" end if testName then test = suite[testName] if not _.isValidTestPair(testName, test) then return nil, nil, "No such test '" .. suiteName .. "." .. testName .. "'" end end end return suite, test end function _.isValidTestPair(testName, testFunc) if type(testFunc) ~= "function" then return false end if testName == "setup" or testName == "teardown" then return false end return true end