149 lines
3.4 KiB
Lua
149 lines
3.4 KiB
Lua
--[[
|
|
Represents the state relevant while executing a test plan.
|
|
|
|
Used by TestRunner to produce a TestResults object.
|
|
|
|
Uses the same tree building structure as TestPlanBuilder; TestSession keeps
|
|
track of a stack of nodes that represent the current path through the tree.
|
|
]]
|
|
|
|
local TestEnum = require(script.Parent.TestEnum)
|
|
local TestResults = require(script.Parent.TestResults)
|
|
|
|
local TestSession = {}
|
|
|
|
TestSession.__index = TestSession
|
|
|
|
--[[
|
|
Create a TestSession related to the given TestPlan.
|
|
|
|
The resulting TestResults object will be linked to this TestPlan.
|
|
]]
|
|
function TestSession.new(plan)
|
|
local self = {
|
|
results = TestResults.new(plan),
|
|
nodeStack = {},
|
|
hasFocusNodes = false
|
|
}
|
|
|
|
setmetatable(self, TestSession)
|
|
|
|
return self
|
|
end
|
|
|
|
--[[
|
|
Calculate success, failure, and skipped test counts in the tree at the
|
|
current point in the execution.
|
|
]]
|
|
function TestSession:calculateTotals()
|
|
local results = self.results
|
|
|
|
results.successCount = 0
|
|
results.failureCount = 0
|
|
results.skippedCount = 0
|
|
|
|
results:visitAllNodes(function(node)
|
|
local status = node.status
|
|
local nodeType = node.planNode.type
|
|
|
|
if nodeType == TestEnum.NodeType.It then
|
|
if status == TestEnum.TestStatus.Success then
|
|
results.successCount = results.successCount + 1
|
|
elseif status == TestEnum.TestStatus.Failure then
|
|
results.failureCount = results.failureCount + 1
|
|
elseif status == TestEnum.TestStatus.Skipped then
|
|
results.skippedCount = results.skippedCount + 1
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
--[[
|
|
Gathers all of the errors reported by tests and puts them at the top level
|
|
of the TestResults object.
|
|
]]
|
|
function TestSession:gatherErrors()
|
|
local results = self.results
|
|
|
|
results.errors = {}
|
|
|
|
results:visitAllNodes(function(node)
|
|
if #node.errors > 0 then
|
|
for _, message in ipairs(node.errors) do
|
|
table.insert(results.errors, message)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
--[[
|
|
Calculates test totals, verifies the tree is valid, and returns results.
|
|
]]
|
|
function TestSession:finalize()
|
|
if #self.nodeStack ~= 0 then
|
|
error("Cannot finalize TestResults with nodes still on the stack!", 2)
|
|
end
|
|
|
|
self:calculateTotals()
|
|
self:gatherErrors()
|
|
|
|
return self.results
|
|
end
|
|
|
|
--[[
|
|
Create a new test result node and push it onto the navigation stack.
|
|
]]
|
|
function TestSession:pushNode(planNode)
|
|
local node = TestResults.createNode(planNode)
|
|
|
|
local lastNode = self.nodeStack[#self.nodeStack] or self.results
|
|
|
|
table.insert(lastNode.children, node)
|
|
table.insert(self.nodeStack, node)
|
|
|
|
return node
|
|
end
|
|
|
|
--[[
|
|
Pops a node off of the navigation stack.
|
|
]]
|
|
function TestSession:popNode()
|
|
assert(#self.nodeStack > 0, "Tried to pop from an empty node stack!")
|
|
return table.remove(self.nodeStack, #self.nodeStack)
|
|
end
|
|
|
|
--[[
|
|
Tells whether the current test we're in should be skipped.
|
|
]]
|
|
function TestSession:shouldSkip()
|
|
-- If our test tree had any exclusive tests, then normal tests are skipped!
|
|
if self.hasFocusNodes then
|
|
for i = #self.nodeStack, 1, -1 do
|
|
local node = self.nodeStack[i]
|
|
|
|
-- Skipped tests are still skipped
|
|
if node.planNode.modifier == TestEnum.NodeModifier.Skip then
|
|
return true
|
|
end
|
|
|
|
-- Focused tests are the only ones that aren't skipped
|
|
if node.planNode.modifier == TestEnum.NodeModifier.Focus then
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
else
|
|
for i = #self.nodeStack, 1, -1 do
|
|
local node = self.nodeStack[i]
|
|
|
|
if node.planNode.modifier == TestEnum.NodeModifier.Skip then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
return TestSession |