mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
259 lines
9.5 KiB
Matlab
259 lines
9.5 KiB
Matlab
classdef TestRunDisplay < TestRunMonitor
|
|
%TestRunDisplay Print test suite execution results.
|
|
% TestRunDisplay is a subclass of TestRunMonitor. If a TestRunDisplay
|
|
% object is passed to the run method of a TestComponent, such as a
|
|
% TestSuite or a TestCase, it will print information to the Command
|
|
% Window (or specified file handle) as the test run proceeds.
|
|
%
|
|
% TestRunDisplay methods:
|
|
% testComponentStarted - Update Command Window display
|
|
% testComponentFinished - Update Command Window display
|
|
% testCaseFailure - Log test failure information
|
|
% testCaseError - Log test error information
|
|
%
|
|
% TestRunDisplay properties:
|
|
% TestCaseCount - Number of test cases executed
|
|
% Faults - Struct array of test fault info
|
|
%
|
|
% See also TestRunLogger, TestRunMonitor, TestSuite
|
|
|
|
% Steven L. Eddins
|
|
% Copyright 2008-2010 The MathWorks, Inc.
|
|
|
|
properties (SetAccess = private)
|
|
%TestCaseCount - Number of test cases executed
|
|
TestCaseCount
|
|
|
|
%Faults - Struct array of test fault info
|
|
% Faults is a struct array with these fields:
|
|
% Type - either 'failure' or 'error'
|
|
% TestCase - the TestCase object that suffered the fault
|
|
% Exception - the MException thrown when the fault occurred
|
|
Faults = struct('Type', {}, 'TestCase', {}, 'Exception', {});
|
|
|
|
end
|
|
|
|
properties (SetAccess = private, GetAccess = private)
|
|
%InitialTic - Out of tic at beginning of test run
|
|
InitialTic
|
|
|
|
%InitialComponent First test component executed
|
|
% InitialComponent is set to the first test component executed in the
|
|
% test run. This component is saved so that the end of the test run
|
|
% can be identified.
|
|
InitialComponent = []
|
|
|
|
end
|
|
|
|
properties (Access = protected)
|
|
%FileHandle - Handle used by fprintf for displaying results.
|
|
% Default value of 1 displays to Command Window.
|
|
FileHandle = 1
|
|
end
|
|
|
|
|
|
methods
|
|
function self = TestRunDisplay(output)
|
|
if nargin > 0
|
|
if ischar(output)
|
|
self.FileHandle = fopen(output, 'w');
|
|
if self.FileHandle < 0
|
|
error('xunit:TestRunDisplay:FileOpenError', ...
|
|
'Could not open file "%s" for writing.', ...
|
|
filename);
|
|
end
|
|
else
|
|
self.FileHandle = output;
|
|
end
|
|
end
|
|
end
|
|
|
|
function testComponentStarted(self, component)
|
|
%testComponentStarted Update Command Window display
|
|
% If the InitialComponent property is not yet set,
|
|
% obj.testComponentStarted(component) sets the property and calls
|
|
% obj.testRunStarted(component).
|
|
|
|
if isempty(self.InitialComponent)
|
|
self.InitialComponent = component;
|
|
self.testRunStarted(component);
|
|
end
|
|
end
|
|
|
|
function testComponentFinished(self, component, did_pass)
|
|
%testComponentFinished Update Command Window display
|
|
% If component is a TestCase object, then
|
|
% obj.testComponentFinished(component, did_pass) prints pass/fail
|
|
% information to the Command Window.
|
|
%
|
|
% If component is the InitialComponent, then
|
|
% obj.testRunFinished(did_pass) is called.
|
|
|
|
if isa(component, 'TestCase')
|
|
self.TestCaseCount = self.TestCaseCount + 1;
|
|
if did_pass
|
|
fprintf(self.FileHandle, '.');
|
|
else
|
|
fprintf(self.FileHandle, 'F');
|
|
end
|
|
line_length = 20;
|
|
if mod(self.TestCaseCount, line_length) == 0
|
|
fprintf(self.FileHandle, '\n');
|
|
end
|
|
end
|
|
|
|
if isequal(component, self.InitialComponent)
|
|
self.testRunFinished(did_pass);
|
|
end
|
|
end
|
|
|
|
function testCaseFailure(self, test_case, failure_exception)
|
|
%testCaseFailure Log test failure information
|
|
% obj.testCaseFailure(test_case, failure_exception) logs the test
|
|
% case failure information.
|
|
|
|
self.logFault('failure', test_case, ...
|
|
failure_exception);
|
|
end
|
|
|
|
function testCaseError(self, test_case, error_exception)
|
|
%testCaseError Log test error information
|
|
% obj.testCaseError(test_case, error_exception) logs the test
|
|
% case error information.
|
|
|
|
self.logFault('error', test_case, ...
|
|
error_exception);
|
|
end
|
|
|
|
end
|
|
|
|
methods (Access = protected)
|
|
function testRunStarted(self, component)
|
|
%testRunStarted Update Command Window display
|
|
% obj.testRunStarted(component) displays information about the test
|
|
% run to the Command Window.
|
|
|
|
self.InitialTic = tic;
|
|
self.TestCaseCount = 0;
|
|
num_cases = component.numTestCases();
|
|
if num_cases == 1
|
|
str = 'case';
|
|
else
|
|
str = 'cases';
|
|
end
|
|
fprintf(self.FileHandle, 'Starting test run with %d test %s.\n', ...
|
|
num_cases, str);
|
|
end
|
|
|
|
function testRunFinished(self, did_pass)
|
|
%testRunFinished Update Command Window display
|
|
% obj.testRunFinished(component) displays information about the test
|
|
% run results, including any test failures, to the Command Window.
|
|
|
|
if did_pass
|
|
result = 'PASSED';
|
|
else
|
|
result = 'FAILED';
|
|
end
|
|
|
|
fprintf(self.FileHandle, '\n%s in %.3f seconds.\n', result, toc(self.InitialTic));
|
|
|
|
self.displayFaults();
|
|
end
|
|
|
|
|
|
|
|
function logFault(self, type, test_case, exception)
|
|
%logFault Log test fault information
|
|
% obj.logFault(type, test_case, exception) logs test fault
|
|
% information. type is either 'failure' or 'error'. test_case is a
|
|
% TestCase object. exception is an MException object.
|
|
|
|
self.Faults(end + 1).Type = type;
|
|
self.Faults(end).TestCase = test_case;
|
|
self.Faults(end).Exception = exception;
|
|
end
|
|
|
|
function displayFaults(self)
|
|
%displayFaults Display test fault info to Command Window
|
|
% obj.displayFaults() displays a summary of each test failure and
|
|
% test error to the command window.
|
|
for k = 1:numel(self.Faults)
|
|
faultData = self.Faults(k);
|
|
if strcmp(faultData.Type, 'failure')
|
|
str = 'Failure';
|
|
else
|
|
str = 'Error';
|
|
end
|
|
fprintf(self.FileHandle, '\n===== Test Case %s =====\nLocation: %s\nName: %s\n\n', str, ...
|
|
faultData.TestCase.Location, faultData.TestCase.Name);
|
|
displayStack(filterStack(faultData.Exception.stack), ...
|
|
self.FileHandle);
|
|
fprintf(self.FileHandle, '\n%s\n', faultData.Exception.message);
|
|
|
|
fprintf(self.FileHandle, '\n');
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function displayStack(stack, file_handle)
|
|
%displayStack Display stack trace from MException instance
|
|
% displayStack(stack) prints information about an exception stack to the
|
|
% command window.
|
|
|
|
for k = 1:numel(stack)
|
|
filename = stack(k).file;
|
|
linenumber = stack(k).line;
|
|
href = sprintf('matlab: opentoline(''%s'',%d)', filename, linenumber);
|
|
fprintf(file_handle, '%s at <a href="%s">line %d</a>\n', filename, href, linenumber);
|
|
end
|
|
end
|
|
|
|
function new_stack = filterStack(stack)
|
|
%filterStack Remove unmeaningful stack trace calls
|
|
% new_stack = filterStack(stack) removes from the input stack trace calls
|
|
% that are framework functions and methods that are not likely to be
|
|
% meaningful to the user.
|
|
|
|
% Testing stack traces follow this common pattern:
|
|
%
|
|
% 1. The first function call in the trace is often one of the assert functions
|
|
% in the framework directory. This is useful to see.
|
|
%
|
|
% 2. The next function calls are in the user-written test functions/methods and
|
|
% the user-written code under test. These calls are useful to see.
|
|
%
|
|
% 3. The final set of function calls are methods in the various framework
|
|
% classes. There are usually several of these calls, which clutter up the
|
|
% stack display without being that useful.
|
|
%
|
|
% The pattern above suggests the following stack filtering strategy: Once the
|
|
% stack trace has left the framework directory, do not follow the stack trace back
|
|
% into the framework directory.
|
|
|
|
mtest_directory = fileparts(which('runtests'));
|
|
last_keeper = numel(stack);
|
|
have_left_mtest_directory = false;
|
|
for k = 1:numel(stack)
|
|
directory = fileparts(stack(k).file);
|
|
if have_left_mtest_directory
|
|
if strcmp(directory, mtest_directory)
|
|
% Stack trace has reentered mtest directory.
|
|
last_keeper = k - 1;
|
|
break;
|
|
end
|
|
else
|
|
if ~strcmp(directory, mtest_directory)
|
|
have_left_mtest_directory = true;
|
|
end
|
|
end
|
|
end
|
|
|
|
new_stack = stack(1:last_keeper);
|
|
|
|
end
|
|
|