123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- ---
- -- 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 test objects via the 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.
- -- Use "*" to match any part of a suite or test name
- -- @return
- -- On success, returns an array of test objects, which should be considered opaque.
- -- On failure, returns `nil` and an error.
- ---
- function m.getTestsWithIdentifier(identifier)
- local suiteName, testName = m.parseTestIdentifier(identifier)
- if suiteName ~= nil and string.contains(suiteName, "*") then
- local tests = {}
- local pattern = string.gsub(suiteName, "*", ".*")
- for _suiteName, suite in pairs(_.suites) do
- local length = string.len(_suiteName)
- local start, finish = string.find(_suiteName, pattern)
- if start == 1 and finish == length then
- if testName ~= nil then
- if string.contains(testName, "*") then
- local testPattern = string.gsub(testName, "*", ".*")
- for _testName, test in pairs(suite) do
- length = string.len(_testName)
- start, finish = string.find(_testName, testPattern)
- if start == 1 and finish == length then
- table.insert(tests, {
- suiteName = _suiteName,
- suite = suite,
- testName = _testName,
- testFunction = test,
- })
- end
- end
- else
- table.insert(tests, {
- suiteName = _suiteName,
- suite = suite,
- testName = testName,
- testFunction = suite[testName],
- })
- end
- else
- table.insert(tests, {
- suiteName = _suiteName,
- suite = suite,
- testName = nil,
- testFunction = nil,
- })
- end
- end
- end
-
- return tests
- else
- 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
- 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
|