mirror of
https://github.com/Cantera/cantera.git
synced 2024-07-07 04:53:34 -05:00
[MATLAB-legacy] Remove ext/matlab_xunit
This commit is contained in:
parent
5e275fc63d
commit
5b8a0a4ecc
|
@ -1,24 +0,0 @@
|
|||
% UTILS Utility package for MATLAB xUnit Test Framework
|
||||
%
|
||||
% Array Comparison
|
||||
% compareFloats - Compare floating-point arrays using tolerance
|
||||
%
|
||||
% Test Case Discovery Functions
|
||||
% isTestCaseSubclass - True for name of TestCase subclass
|
||||
%
|
||||
% String Functions
|
||||
% arrayToString - Convert array to string for display
|
||||
% comparisonMessage - Assertion message string for comparing two arrays
|
||||
% containsRegexp - True if string contains regular expression
|
||||
% isSetUpString - True for string that looks like a setup function
|
||||
% isTearDownString - True for string that looks like teardown function
|
||||
% isTestString - True for string that looks like a test function
|
||||
% stringToCellArray - Convert string to cell array of strings
|
||||
%
|
||||
% Miscellaneous Functions
|
||||
% generateDoc - Publish test scripts in mtest/doc
|
||||
% parseFloatAssertInputs - Common input-parsing logic for several functions
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
function s = arrayToString(A)
|
||||
%arrayToString Convert array to string for display.
|
||||
% S = arrayToString(A) converts the array A into a string suitable for
|
||||
% including in assertion messages. Small arrays are converted using disp(A).
|
||||
% Large arrays are displayed similar to the way structure field values display
|
||||
% using disp.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2009 The MathWorks, Inc.
|
||||
|
||||
if isTooBigToDisp(A)
|
||||
s = dispAsStructField(A);
|
||||
else
|
||||
s = dispAsArray(A);
|
||||
end
|
||||
|
||||
%===============================================================================
|
||||
function tf = isTooBigToDisp(A)
|
||||
% Use a heuristic to determine if the array is to convert to a string using
|
||||
% disp. The heuristic is based on the size of the array in bytes, as reported
|
||||
% by the whos function.
|
||||
|
||||
whos_output = whos('A');
|
||||
byte_threshold = 1000;
|
||||
tf = whos_output.bytes > byte_threshold;
|
||||
|
||||
%===============================================================================
|
||||
function s = dispAsArray(A)
|
||||
% Convert A to a string using disp. Remove leading and trailing blank lines.
|
||||
|
||||
s = evalc('disp(A)');
|
||||
if isempty(s)
|
||||
% disp displays nothing for some kinds of empty arrays.
|
||||
s = dispAsStructField(A);
|
||||
else
|
||||
s = postprocessDisp(s);
|
||||
end
|
||||
|
||||
%===============================================================================
|
||||
function s = dispAsStructField(A)
|
||||
% Convert A to a string using structure field display.
|
||||
|
||||
b.A = A;
|
||||
s = evalc('disp(b)');
|
||||
s = postprocessStructDisp(s);
|
||||
|
||||
%===============================================================================
|
||||
function out = postprocessDisp(in)
|
||||
% Remove leading and trailing blank lines from input string. Don't include a
|
||||
% newline at the end.
|
||||
|
||||
lines = xunit.utils.stringToCellArray(in);
|
||||
|
||||
% Remove leading blank lines.
|
||||
lines = removeLeadingBlankLines(lines);
|
||||
|
||||
% Remove trailing blank lines.
|
||||
while ~isempty(lines) && isBlankLine(lines{end})
|
||||
lines(end) = [];
|
||||
end
|
||||
|
||||
% Convert cell of strings to single string with newlines. Don't put a newline
|
||||
% at the end.
|
||||
out = sprintf('%s\n', lines{1:end-1});
|
||||
out = [out, lines{end}];
|
||||
|
||||
%===============================================================================
|
||||
function out = postprocessStructDisp(in)
|
||||
% Return the portion of the display string to the right of the colon in the
|
||||
% output of the first structure field. Input is a string.
|
||||
|
||||
lines = xunit.utils.stringToCellArray(in);
|
||||
|
||||
% Remove leading blank lines
|
||||
lines = removeLeadingBlankLines(lines);
|
||||
|
||||
line = lines{1};
|
||||
idx = find(line == ':');
|
||||
out = line((idx+2):end); % struct fields display with blank space following colon
|
||||
|
||||
%===============================================================================
|
||||
function out = removeLeadingBlankLines(in)
|
||||
% Input and output are cell arrays of strings.
|
||||
|
||||
out = in;
|
||||
while ~isempty(out) && isBlankLine(out{1})
|
||||
out(1) = [];
|
||||
end
|
||||
|
||||
%===============================================================================
|
||||
function tf = isBlankLine(line)
|
||||
% Input is a string.
|
||||
|
||||
tf = all(isspace(line));
|
||||
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
function result = compareFloats(varargin)
|
||||
%compareFloats Compare floating-point arrays using tolerance.
|
||||
% result = compareFloats(A, B, compare_type, tol_type, tol, floor_tol)
|
||||
% compares the floating-point arrays A and B using a tolerance. compare_type
|
||||
% is either 'elementwise' or 'vector'. tol_type is either 'relative' or
|
||||
% 'absolute'. tol and floor_tol are the scalar tolerance values.
|
||||
%
|
||||
% There are four different tolerance tests used, depending on the comparison
|
||||
% type and the tolerance type:
|
||||
%
|
||||
% 1. Comparison type: 'elementwise' Tolerance type: 'relative'
|
||||
%
|
||||
% all( abs(A(:) - B(:)) <= tol * max(abs(A(:)), abs(B(:))) + floor_tol )
|
||||
%
|
||||
% 2. Comparison type: 'elementwise' Tolerance type: 'absolute'
|
||||
%
|
||||
% all( abs(A(:) - B(:) <= tol )
|
||||
%
|
||||
% 3. Comparison type: 'vector' Tolerance type: 'relative'
|
||||
%
|
||||
% norm(A(:) - B(:) <= tol * max(norm(A(:)), norm(B(:))) + floor_tol
|
||||
%
|
||||
% 4. Comparison type: 'vector' Tolerance type: 'absolute'
|
||||
%
|
||||
% norm(A(:) - B(:)) <= tol
|
||||
%
|
||||
% Note that floor_tol is not used when the tolerance type is 'absolute'.
|
||||
%
|
||||
% compare_type, tol_type, tol, and floor_tol are all optional inputs. The
|
||||
% default value for compare_type is 'elementwise'. The default value for
|
||||
% tol_type is 'relative'. If both A and B are double, then the default value
|
||||
% for tol is sqrt(eps), and the default value for floor_tol is eps. If either
|
||||
% A or B is single, then the default value for tol is sqrt(eps('single')), and
|
||||
% the default value for floor_tol is eps('single').
|
||||
%
|
||||
% If A or B is complex, then the tolerance test is applied independently to
|
||||
% the real and imaginary parts.
|
||||
%
|
||||
% For elementwise comparisons, compareFloats returns true for two elements
|
||||
% that are both NaN, or for two infinite elements that have the same sign.
|
||||
% For vector comparisons, compareFloats returns false if any input elements
|
||||
% are infinite or NaN.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
if nargin >= 3
|
||||
% compare_type specified. Grab it and then use parseFloatAssertInputs to
|
||||
% process the remaining input arguments.
|
||||
compare_type = varargin{3};
|
||||
varargin(3) = [];
|
||||
if isempty(strcmp(compare_type, {'elementwise', 'vector'}))
|
||||
error('compareFloats:unrecognizedCompareType', ...
|
||||
'COMPARE_TYPE must be ''elementwise'' or ''vector''.');
|
||||
end
|
||||
else
|
||||
compare_type = 'elementwise';
|
||||
end
|
||||
|
||||
params = xunit.utils.parseFloatAssertInputs(varargin{:});
|
||||
|
||||
A = params.A(:);
|
||||
B = params.B(:);
|
||||
|
||||
switch compare_type
|
||||
case 'elementwise'
|
||||
magFcn = @abs;
|
||||
|
||||
case 'vector'
|
||||
magFcn = @norm;
|
||||
|
||||
otherwise
|
||||
error('compareFloats:unrecognizedCompareType', ...
|
||||
'COMPARE_TYPE must be ''elementwise'' or ''vector''.');
|
||||
end
|
||||
|
||||
switch params.ToleranceType
|
||||
case 'relative'
|
||||
coreCompareFcn = @(A, B) magFcn(A - B) <= ...
|
||||
params.Tolerance * max(magFcn(A), magFcn(B)) + ...
|
||||
params.FloorTolerance;
|
||||
|
||||
case 'absolute'
|
||||
coreCompareFcn = @(A, B) magFcn(A - B) <= params.Tolerance;
|
||||
|
||||
otherwise
|
||||
error('compareFloats:unrecognizedToleranceType', ...
|
||||
'TOL_TYPE must be ''relative'' or ''absolute''.');
|
||||
end
|
||||
|
||||
if strcmp(compare_type, 'elementwise')
|
||||
compareFcn = @(A, B) ( coreCompareFcn(A, B) | bothNaN(A, B) | sameSignInfs(A, B) ) & ...
|
||||
~oppositeSignInfs(A, B) & ...
|
||||
~finiteAndInfinite(A, B);
|
||||
else
|
||||
compareFcn = @(A, B) coreCompareFcn(A, B) & ...
|
||||
isfinite(magFcn(A)) & ...
|
||||
isfinite(magFcn(B));
|
||||
end
|
||||
|
||||
if isreal(A) && isreal(B)
|
||||
result = compareFcn(A, B);
|
||||
else
|
||||
result = compareFcn(real(A), real(B)) & compareFcn(imag(A), imag(B));
|
||||
end
|
||||
|
||||
result = all(result);
|
||||
|
||||
%===============================================================================
|
||||
function out = bothNaN(A, B)
|
||||
|
||||
out = isnan(A) & isnan(B);
|
||||
|
||||
%===============================================================================
|
||||
function out = oppositeSignInfs(A, B)
|
||||
|
||||
out = isinf(A) & isinf(B) & (sign(A) ~= sign(B));
|
||||
|
||||
%===============================================================================
|
||||
function out = sameSignInfs(A, B)
|
||||
|
||||
out = isinf(A) & isinf(B) & (sign(A) == sign(B));
|
||||
|
||||
%===============================================================================
|
||||
function out = finiteAndInfinite(A, B)
|
||||
|
||||
out = xor(isinf(A), isinf(B));
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
function msg = comparisonMessage(user_message, assertion_message, A, B)
|
||||
%comparisonMessage Generate assertion message when comparing two arrays.
|
||||
% msg = comparisonMessage(user_message, assertion_message, A, B) returns a
|
||||
% string appropriate to use in a call to throw inside an assertion function
|
||||
% that compares two arrays A and B.
|
||||
%
|
||||
% The string returned has the following form:
|
||||
%
|
||||
% <user_message>
|
||||
% <assertion_message>
|
||||
%
|
||||
% First input:
|
||||
% <string representation of value of A>
|
||||
%
|
||||
% Second input:
|
||||
% <string representation of value of B>
|
||||
%
|
||||
% user_message can be the empty string, '', in which case user_message is
|
||||
% skipped.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2009 The MathWorks, Inc.
|
||||
|
||||
msg = sprintf('%s\n\n%s\n%s\n\n%s\n%s', ...
|
||||
assertion_message, ...
|
||||
'First input:', ...
|
||||
xunit.utils.arrayToString(A), ...
|
||||
'Second input:', ...
|
||||
xunit.utils.arrayToString(B));
|
||||
|
||||
if ~isempty(user_message)
|
||||
msg = sprintf('%s\n%s', user_message, msg);
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
function tf = containsRegexp(str, exp)
|
||||
%containsRegexp True if string contains regular expression
|
||||
% TF = containsRegexp(str, exp) returns true if the string str contains the
|
||||
% regular expression exp. If str is a cell array of strings, then
|
||||
% containsRegexp tests each string in the cell array, returning the results in
|
||||
% a logical array with the same size as str.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
% Convert to canonical input form: A cell array of strings.
|
||||
if ~iscell(str)
|
||||
str = {str};
|
||||
end
|
||||
|
||||
matches = regexp(str, exp);
|
||||
tf = ~cellfun('isempty', matches);
|
|
@ -1,14 +0,0 @@
|
|||
function generateDoc
|
||||
%generateDoc Publish the example scripts in the doc directory
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
doc_dir = fullfile(fileparts(which('runtests')), '..', 'doc');
|
||||
addpath(doc_dir);
|
||||
cd(doc_dir)
|
||||
mfiles = dir('*.m');
|
||||
for k = 1:numel(mfiles)
|
||||
publish(mfiles(k).name);
|
||||
cd(doc_dir)
|
||||
end
|
|
@ -1,46 +0,0 @@
|
|||
function same = isAlmostEqual(A, B, reltol)
|
||||
%isAlmostEqual Equality test using relative tolerance
|
||||
% same = isAlmostEqual(A, B, reltol), for two floating-point arrays A and B,
|
||||
% tests A and B for equality using the specified relative tolerance.
|
||||
% isAlmostEqual returns true if the following relationship is satisfied for
|
||||
% all values in A and B:
|
||||
%
|
||||
% abs(A - B) ./ max(abs(A), abs(B)) <= reltol
|
||||
%
|
||||
% same = isAlmostEqual(A, B) uses the following value for the relative
|
||||
% tolerance:
|
||||
%
|
||||
% 100 * max(eps(class(A)), eps(class(B)))
|
||||
%
|
||||
% If either A or B is not a floating-point array, then isAlmostEqual returns
|
||||
% the result of isequal(A, B).
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
if ~isfloat(A) || ~isfloat(B)
|
||||
same = isequal(A, B);
|
||||
return
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
reltol = 100 * max(eps(class(A)), eps(class(B)));
|
||||
end
|
||||
|
||||
if ~isequal(size(A), size(B))
|
||||
same = false;
|
||||
return
|
||||
end
|
||||
|
||||
A = A(:);
|
||||
B = B(:);
|
||||
|
||||
delta = abs(A - B) ./ max(max(abs(A), abs(B)), 1);
|
||||
|
||||
% Some floating-point values require special handling.
|
||||
delta((A == 0) & (B == 0)) = 0;
|
||||
delta(isnan(A) & isnan(B)) = 0;
|
||||
delta((A == Inf) & (B == Inf)) = 0;
|
||||
delta((A == -Inf) & (B == -Inf)) = 0;
|
||||
|
||||
same = all(delta <= reltol);
|
|
@ -1,12 +0,0 @@
|
|||
function tf = isSetUpString(str)
|
||||
%isSetUpString True if string looks like the name of a setup function
|
||||
% tf = isSetUpString(str) returns true if the string str looks like the name
|
||||
% of a setup function. If str is a cell array of strings, then isSetUpString
|
||||
% tests each string in the cell array, returning the results in a logical
|
||||
% array with the same size as str.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
setup_exp = '^[sS]et[uU]p';
|
||||
tf = xunit.utils.containsRegexp(str, setup_exp);
|
|
@ -1,12 +0,0 @@
|
|||
function tf = isTearDownString(str)
|
||||
%isTearDownString True if string looks like the name of a teardown function
|
||||
% tf = isTearDownString(str) returns true if the string str looks like the
|
||||
% name of a teardown function. If str is a cell array of strings, then
|
||||
% isTearDownString tests each string in the cell array, returning the results
|
||||
% in a logical array with the same size as str.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
setup_exp = '^[tT]ear[dD]own';
|
||||
tf = xunit.utils.containsRegexp(str, setup_exp);
|
|
@ -1,39 +0,0 @@
|
|||
function tf = isTestCaseSubclass(name)
|
||||
%isTestCaseSubclass True for name of a TestCase subclass
|
||||
% tf = isTestCaseSubclass(name) returns true if the string name is the name of
|
||||
% a TestCase subclass on the MATLAB path.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
tf = false;
|
||||
|
||||
class_meta = meta.class.fromName(name);
|
||||
if isempty(class_meta)
|
||||
% Not the name of a class
|
||||
return;
|
||||
end
|
||||
|
||||
if strcmp(class_meta.Name, 'TestCase')
|
||||
tf = true;
|
||||
else
|
||||
tf = isMetaTestCaseSubclass(class_meta);
|
||||
end
|
||||
|
||||
function tf = isMetaTestCaseSubclass(class_meta)
|
||||
|
||||
tf = false;
|
||||
|
||||
if strcmp(class_meta.Name, 'TestCase')
|
||||
tf = true;
|
||||
else
|
||||
% Invoke function recursively on parent classes.
|
||||
super_classes = class_meta.SuperClasses;
|
||||
for k = 1:numel(super_classes)
|
||||
if isMetaTestCaseSubclass(super_classes{k})
|
||||
tf = true;
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
function tf = isTestString(str)
|
||||
%isTestString True if string looks like the name of a test
|
||||
% tf = isTestString(str) returns true if the string str looks like the name of
|
||||
% a test. If str is a cell array of strings, then isTestString tests each
|
||||
% string in the cell array, returning the results in a logical array with the
|
||||
% same size as str.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
test_at_beginning = '^[tT]est';
|
||||
test_at_end = '[tT]est$';
|
||||
|
||||
tf = xunit.utils.containsRegexp(str, test_at_beginning) | ...
|
||||
xunit.utils.containsRegexp(str, test_at_end);
|
|
@ -1,56 +0,0 @@
|
|||
function params = parseFloatAssertInputs(varargin)
|
||||
%parseFloatAssertInputs Parse inputs for floating-point assertion functions.
|
||||
% params = parseFloatAssertInputs(varargin) parses the input arguments for
|
||||
% assertElementsAlmostEqual, assertVectorsAlmostEqual, and compareFcn. It
|
||||
% returns a parameter struct containing the fields:
|
||||
%
|
||||
% A B Message ToleranceType Tolerance FloorTolerance
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
error(nargchk(2, 6, nargin, 'struct'));
|
||||
|
||||
params = struct('A', {[]}, 'B', {[]}, 'ToleranceType', {[]}, ...
|
||||
'Tolerance', {[]}, 'FloorTolerance', {[]}, 'Message', {''});
|
||||
|
||||
% The first two input arguments are always A and B.
|
||||
params.A = varargin{1};
|
||||
params.B = varargin{2};
|
||||
varargin(1:2) = [];
|
||||
|
||||
% If the last argument is a message string, process it and remove it from the list.
|
||||
if (numel(varargin) >= 1) && ischar(varargin{end}) && ...
|
||||
~any(strcmp(varargin{end}, {'relative', 'absolute'}))
|
||||
params.Message = varargin{end};
|
||||
varargin(end) = [];
|
||||
else
|
||||
params.Message = '';
|
||||
end
|
||||
|
||||
try
|
||||
epsilon = max(eps(class(params.A)), eps(class(params.B)));
|
||||
catch
|
||||
epsilon = eps;
|
||||
end
|
||||
|
||||
if numel(varargin) < 3
|
||||
% floor_tol not specified; set default.
|
||||
params.FloorTolerance = sqrt(epsilon);
|
||||
else
|
||||
params.FloorTolerance = varargin{3};
|
||||
end
|
||||
|
||||
if numel(varargin) < 2
|
||||
% tol not specified; set default.
|
||||
params.Tolerance = sqrt(epsilon);
|
||||
else
|
||||
params.Tolerance = varargin{2};
|
||||
end
|
||||
|
||||
if numel(varargin) < 1
|
||||
% tol_type not specified; set default.
|
||||
params.ToleranceType = 'relative';
|
||||
else
|
||||
params.ToleranceType = varargin{1};
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
function c = stringToCellArray(s)
|
||||
%stringToCellArray Convert string with newlines to cell array of strings.
|
||||
% C = stringToCellArray(S) converts the input string S to a cell array of
|
||||
% strings, breaking up S at new lines.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2009 The MathWorks, Inc.
|
||||
|
||||
if isempty(s)
|
||||
c = cell(0, 1);
|
||||
else
|
||||
c = textscan(s, '%s', 'Delimiter', '\n', 'Whitespace', '');
|
||||
c = c{1};
|
||||
end
|
|
@ -1,30 +0,0 @@
|
|||
classdef CommandWindowTestRunDisplay < TestRunDisplay
|
||||
%CommandWindowTestRunDisplay Print test suite execution results to Command Window.
|
||||
% CommandWindowTestRunDisplay is a subclass of TestRunMonitor. If a
|
||||
% CommandWindowTestRunDisplay 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 as the test run proceeds.
|
||||
%
|
||||
% CommandWindowTestRunDisplay methods:
|
||||
% testComponentStarted - Update Command Window display
|
||||
% testComponentFinished - Update Command Window display
|
||||
% testCaseFailure - Log test failure information
|
||||
% testCaseError - Log test error information
|
||||
%
|
||||
% CommandWindowTestRunDisplay 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.
|
||||
|
||||
methods
|
||||
function self = CommandWindowTestRunDisplay
|
||||
self = self@TestRunDisplay(1);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
% MATLAB xUnit Test Framework
|
||||
% Version 3.1 (R2010b) 19-Nov-2010
|
||||
%
|
||||
% Running Unit Tests
|
||||
% runtests - Run unit tests
|
||||
%
|
||||
% Writing Unit Tests
|
||||
% assertElementsAlmostEqual - Assert floating-point array elements almost equal
|
||||
% assertEqual - Assert that inputs are equal
|
||||
% assertFilesEqual - Assert that two files have the same content
|
||||
% assertExceptionThrown - Assert that specified exception is thrown
|
||||
% assertFalse - Assert that input condition is false
|
||||
% assertTrue - Assert that input condition is true
|
||||
% assertVectorsAlmostEqual - Assert floating-point vectors almost equal in norm sense
|
||||
% initTestSuite - Utility script used for subfunction-based tests
|
||||
%
|
||||
% Framework Classes
|
||||
% CommandWindowTestRunDisplay - Print test suite results to command window
|
||||
% FunctionHandleTestCase - Test case based on a function handle
|
||||
% TestCase - Class defining interface for test cases
|
||||
% TestCaseInDir - Test case requiring temporary directory change
|
||||
% TestCaseWithAddPath - Test case requiring temporary path modification
|
||||
% TestComponent - Abstract base class for TestCase and TestSuite
|
||||
% TestComponentInDir - Test component requiring temporary directory change
|
||||
% TestLogger - Collect data (silently) from running test suite
|
||||
% TestRunDisplay - Print test suite execution results
|
||||
% TestRunMonitor - Abstract base class for monitoring test suite
|
||||
% TestSuite - Collection of TestComponent objects
|
||||
% TestSuiteInDir - Test suite requiring temporary directory change
|
||||
% %VerboseTestRunDisplay - Print test suite execution results
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
|
@ -1,154 +0,0 @@
|
|||
classdef FunctionHandleTestCase < TestCase
|
||||
%FunctionHandleTestCase Test case based on a function handle
|
||||
% FunctionHandleTestCase is a TestCase subclass. It defines a test case object
|
||||
% that executes by running a function handle instead of by running a method of
|
||||
% the TestCase subclass.
|
||||
%
|
||||
% FunctionHandleTestCase methods:
|
||||
% FunctionHandleTestCase - Constructor
|
||||
% runTestCase - Run function handle test
|
||||
% setUp - Run test-fixture setup function
|
||||
% tearDown - Run test-fixture teardown function
|
||||
%
|
||||
% FunctionHandleTestCase properties:
|
||||
% TestFcn - Function handle of test function
|
||||
% SetupFcn - Function handle of setup function
|
||||
% TeardownFcn - Function handle of teardown function
|
||||
% TestData - Data needed by test function or teardown function
|
||||
%
|
||||
% See also TestCase, TestSuite
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
properties (SetAccess = protected, GetAccess = protected, Hidden = true)
|
||||
%TestFcn - Function handle of test function
|
||||
% If SetupFcn has one or more output arguments, then TestFcn is
|
||||
% called with this syntax:
|
||||
%
|
||||
% TestFcn(data)
|
||||
%
|
||||
% where data is the return value from SetupFcn. Otherwise, TestFcn is
|
||||
% called with no input and no output arguments.
|
||||
TestFcn;
|
||||
|
||||
%SetupFcn - Function handle of setup function
|
||||
% If SetupFcn has one or more output arguments, then SetupFcn is
|
||||
% called with this syntax:
|
||||
%
|
||||
% data = SetupFcn()
|
||||
%
|
||||
% and data will be saved in the TestData property. Otherwise, SetupFcn
|
||||
% is called with no input and no output arguments.
|
||||
SetupFcn;
|
||||
|
||||
%TeardownFcn - Function handle of teardown function
|
||||
% If SetupFcn has one or more output arguments, then TeardownFcn is
|
||||
% called with this syntax:
|
||||
%
|
||||
% TeardownFcn(data)
|
||||
%
|
||||
% were data is the return value from SetupFcn. Otherwise, TeardownFcn
|
||||
% is called with no input and no output arguments.
|
||||
TeardownFcn;
|
||||
|
||||
%TestData - Data needed by test function or teardown function.
|
||||
TestData;
|
||||
end
|
||||
|
||||
methods
|
||||
function self = FunctionHandleTestCase(testFcn, setupFcn, teardownFcn)
|
||||
%FunctionHandleTestCase Constructor
|
||||
% FunctionHandleTestCase(testFcn, setupFcn, teardownFcn) creates a
|
||||
% TestCase object that executes by running the function handle
|
||||
% TestFcn. setupFcn is a function handle that will be executed
|
||||
% before testFcn, and teardownFcn is a function handle that will
|
||||
% be executed after TestFcn. Either setupFcn or teardownFcn can
|
||||
% be empty.
|
||||
%
|
||||
% If setupFcn is function handle that has one output argument,
|
||||
% then the three test functions will be called using these
|
||||
% syntaxes:
|
||||
%
|
||||
% testData = setupFcn();
|
||||
% testFcn(testData);
|
||||
% teardownFcn(testData);
|
||||
%
|
||||
% Otherwise, the three test functions are all called with no input
|
||||
% arguments:
|
||||
%
|
||||
% setupFcn();
|
||||
% TestFcn();
|
||||
% teardownFcn();
|
||||
|
||||
% Call the base class constructor. Give it the name of the
|
||||
% FunctionHandleTestCase method that executes TestFcn.
|
||||
self = self@TestCase('runTestCase');
|
||||
|
||||
self.TestFcn = testFcn;
|
||||
self.SetupFcn = setupFcn;
|
||||
self.TeardownFcn = teardownFcn;
|
||||
|
||||
% Determine the name and M-file location of the function handle.
|
||||
functionHandleInfo = functions(testFcn);
|
||||
self.Name = functionHandleInfo.function;
|
||||
if strcmp(functionHandleInfo.type, 'anonymous')
|
||||
% Anonymous function handles don't have an M-file location.
|
||||
self.Location = '';
|
||||
else
|
||||
self.Location = functionHandleInfo.file;
|
||||
end
|
||||
end
|
||||
|
||||
function runTestCase(self)
|
||||
%runTestCase Run function handle test
|
||||
% test_case.run() calls the test function handle. If a nonempty
|
||||
% SetupFcn was provided and it has at least one output argument,
|
||||
% pass self.TestData to the test function. Otherwise, call the
|
||||
% test function with no input arguments.
|
||||
if ~isempty(self.SetupFcn) && nargout(self.SetupFcn) > 0
|
||||
self.TestFcn(self.TestData);
|
||||
else
|
||||
self.TestFcn();
|
||||
end
|
||||
end
|
||||
|
||||
function setUp(self)
|
||||
%setUp Run test-fixture setup function
|
||||
% If a nonempty SetupFcn was provided, run it. If the SetupFcn
|
||||
% has at least one output argument, capture the first output
|
||||
% argument in instance data (TestData).
|
||||
if ~isempty(self.SetupFcn)
|
||||
if nargout(self.SetupFcn) > 0
|
||||
if nargout(self.SetupFcn) > 1
|
||||
message = sprintf(['A test fixture setup function returns more than one output argument. ', ...
|
||||
'The test harness only calls the setup function with one output argument. ', ...
|
||||
'Return a struct or a cell array from your setup function if you need to bundle several parts together.', ...
|
||||
'\nTest name: %s\nTest location: %s'], ...
|
||||
self.Name, self.Location);
|
||||
warning('xunit:FunctionHandleTestCase:TooManySetupOutputs', ...
|
||||
'%s', message);
|
||||
end
|
||||
self.TestData = self.SetupFcn();
|
||||
else
|
||||
self.SetupFcn();
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tearDown(self)
|
||||
%tearDown Run test-fixture teardown function
|
||||
% If a nonempty TeardownFcn was provided, run it. If there is
|
||||
% TestData (the output of the SetupFcn), then pass it to
|
||||
% TeardownFcn. Otherwise, call TeardownFcn with no input
|
||||
% arguments.
|
||||
if ~isempty(self.TeardownFcn)
|
||||
if ~isempty(self.SetupFcn) && (nargout(self.SetupFcn) > 0)
|
||||
self.TeardownFcn(self.TestData);
|
||||
else
|
||||
self.TeardownFcn();
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
The full Matlab xUnit package (including documentation) is available from:
|
||||
|
||||
http://www.mathworks.com/matlabcentral/fileexchange/22846-matlab-xunit-test-framework
|
|
@ -1,103 +0,0 @@
|
|||
%TestCase Class defining interface for test cases
|
||||
% The TestCase class defines an individual test case.
|
||||
%
|
||||
% Normally a test writer will create their own test class that is a subclass
|
||||
% of TestCase. Each instance of the TestCase subclass that gets created will
|
||||
% be associated with a single test method.
|
||||
%
|
||||
% If a test fixture is needed, override the setUp() and tearDown() methods.
|
||||
%
|
||||
% TestSuite(subclass_name), where subclass_name is the name of a TestCase
|
||||
% subclass, creates a test suite containing one TestCase instance per test
|
||||
% method contained in the subclass.
|
||||
%
|
||||
% A simpler test-writing alternative to use subfunction-based M-file tests.
|
||||
% See the MATLAB xUnit documentation.
|
||||
%
|
||||
% TestCase methods:
|
||||
% TestCase - Constructor
|
||||
% run - Execute the test case
|
||||
%
|
||||
% TestCase properties:
|
||||
% Location - Location of M-file containing the test case
|
||||
% Name - Name of test case
|
||||
%
|
||||
% See also TestComponent, TestSuite
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
classdef TestCase < TestComponent
|
||||
|
||||
properties
|
||||
MethodName
|
||||
end
|
||||
|
||||
methods
|
||||
function self = TestCase(testMethod)
|
||||
%TestCase Constructor
|
||||
% TestCase(methodName) constructs a TestCase object using the
|
||||
% specified testMethod (a string).
|
||||
|
||||
self.MethodName = testMethod;
|
||||
self.Name = testMethod;
|
||||
self.Location = which(class(self));
|
||||
end
|
||||
|
||||
function did_pass = run(self, monitor)
|
||||
%run Execute the test case
|
||||
% test_case.run(monitor) calls the TestCase object's setUp()
|
||||
% method, then the test method, then the tearDown() method.
|
||||
% observer is a TestRunObserver object. The testStarted(),
|
||||
% testFailure(), testError(), and testFinished() methods of
|
||||
% observer are called at the appropriate times. monitor is a
|
||||
% TestRunMonitor object. Typically it is either a TestRunLogger
|
||||
% subclass or a CommandWindowTestRunDisplay subclass.
|
||||
%
|
||||
% test_case.run() automatically uses a
|
||||
% CommandWindowTestRunDisplay object in order to print test
|
||||
% suite execution information to the Command Window.
|
||||
|
||||
if nargin < 2
|
||||
monitor = CommandWindowTestRunDisplay();
|
||||
end
|
||||
|
||||
did_pass = true;
|
||||
monitor.testComponentStarted(self);
|
||||
|
||||
try
|
||||
self.setUp();
|
||||
f = str2func(self.MethodName);
|
||||
|
||||
try
|
||||
% Call the test method.
|
||||
f(self);
|
||||
catch failureException
|
||||
monitor.testCaseFailure(self, failureException);
|
||||
did_pass = false;
|
||||
end
|
||||
|
||||
self.tearDown();
|
||||
|
||||
catch errorException
|
||||
monitor.testCaseError(self, errorException);
|
||||
did_pass = false;
|
||||
end
|
||||
|
||||
monitor.testComponentFinished(self, did_pass);
|
||||
end
|
||||
|
||||
function num = numTestCases(self)
|
||||
num = 1;
|
||||
end
|
||||
|
||||
function print(self, numLeadingBlanks)
|
||||
if nargin < 2
|
||||
numLeadingBlanks = 0;
|
||||
end
|
||||
fprintf('%s%s\n', blanks(numLeadingBlanks), self.Name);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,30 +0,0 @@
|
|||
%TestCaseInDir Test case requiring temporary directory change
|
||||
% The TestCaseInDir class defines a test case that has to be run by first
|
||||
% changing to a specified directory.
|
||||
%
|
||||
% The setUp method adds the starting directory to the path and then uses cd to
|
||||
% change into the specified directory. The tearDown method restores the
|
||||
% original path and directory.
|
||||
%
|
||||
% TestCaseInDir is used by MATLAB xUnit's own test suite in order to test itself.
|
||||
%
|
||||
% TestCaseInDir methods:
|
||||
% TestCaseInDir - Constructor
|
||||
%
|
||||
% See also TestCase, TestCaseWithAddPath, TestComponent
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
classdef TestCaseInDir < TestCase & TestComponentInDir
|
||||
|
||||
methods
|
||||
function self = TestCaseInDir(methodName, testDirectory)
|
||||
%TestCaseInDir Constructor
|
||||
% TestCaseInDir(testName, testDirectory) constructs a test case
|
||||
% using the specified name and located in the specified directory.
|
||||
self = self@TestCase(methodName);
|
||||
self = self@TestComponentInDir(testDirectory);
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,53 +0,0 @@
|
|||
%TestCaseInDir Test case requiring temporary path modification
|
||||
% The TestCaseInDir class defines a test case that has to be run by first
|
||||
% adding a specific directory to the path.
|
||||
%
|
||||
% The setUp method adds the directory to the path, and the tearDown method
|
||||
% restores the original path.
|
||||
%
|
||||
% TestCaseWithAddPath is used by MATLAB xUnit's own test suite in order to test
|
||||
% itself.
|
||||
%
|
||||
% TestCaseWithAddPath methods:
|
||||
% TestCaseWithAddPath - Constructor
|
||||
% setUp - Add test directory to MATLAB path
|
||||
% tearDown - Restore original MATLAB path
|
||||
%
|
||||
% See also TestCase, TestCaseInDir
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
classdef TestCaseWithAddPath < TestCase
|
||||
properties (SetAccess = private, GetAccess = private)
|
||||
%TestDirectory - Directory to be added to the path
|
||||
TestDirectory
|
||||
|
||||
%OriginalPath - Path prior to adding the test directory
|
||||
OriginalPath
|
||||
end
|
||||
|
||||
methods
|
||||
function self = TestCaseWithAddPath(methodName, testDirectory)
|
||||
%TestCaseInDir Constructor
|
||||
% TestCaseInDir(testName, testDirectory) constructs a test case
|
||||
% using the specified name and located in the specified directory.
|
||||
self = self@TestCase(methodName);
|
||||
self.TestDirectory = testDirectory;
|
||||
end
|
||||
|
||||
function setUp(self)
|
||||
%setUp Add test directory to MATLAB path.
|
||||
% test_case.setUp() saves the current path in the OriginalPath
|
||||
% property and then adds the TestDirectory to the MATLAB path.
|
||||
self.OriginalPath = path;
|
||||
addpath(self.TestDirectory);
|
||||
end
|
||||
|
||||
function tearDown(self)
|
||||
%tearDown Restore original MATLAB path
|
||||
% test_case.tearDown() restores the saved MATLAB path.
|
||||
path(self.OriginalPath);
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,59 +0,0 @@
|
|||
classdef TestComponent < handle
|
||||
%TestComponent Abstract base class for TestCase and TestSuite
|
||||
%
|
||||
% TestComponent methods:
|
||||
% run - Run all test cases in test component
|
||||
% print - Display summary of test component to Command Window
|
||||
% numTestCases - Number of test cases in test component
|
||||
% setUp - Initialize test fixture
|
||||
% tearDown - Clean up text fixture
|
||||
%
|
||||
% TestComponent properties:
|
||||
% Name - Name of test component
|
||||
% Location - Directory where test component is defined
|
||||
%
|
||||
% See TestCase, TestSuite
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
properties
|
||||
Name = '';
|
||||
Location = '';
|
||||
end
|
||||
|
||||
properties (Access = 'protected')
|
||||
PrintIndentationSize = 4
|
||||
end
|
||||
|
||||
methods (Abstract)
|
||||
print()
|
||||
%print Display summary of test component to Command Window
|
||||
% obj.print() displays information about the test component to the
|
||||
% Command Window.
|
||||
|
||||
run()
|
||||
%run Execute test cases
|
||||
% obj.run() executes all the test cases in the test component
|
||||
|
||||
numTestCases()
|
||||
%numTestCases Number of test cases in test component
|
||||
end
|
||||
|
||||
methods
|
||||
function setUp(self)
|
||||
%setUp Set up test fixture
|
||||
% test_component.setUp() is called at the beginning of the run()
|
||||
% method. Test writers can override setUp if necessary to
|
||||
% initialize a test fixture.
|
||||
end
|
||||
|
||||
function tearDown(self)
|
||||
%tearDown Tear down test fixture
|
||||
% test_component.tearDown() is at the end of the method. Test
|
||||
% writers can override tearDown if necessary to clean up a test
|
||||
% fixture.
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -1,58 +0,0 @@
|
|||
%TestComponentInDir Test component requiring temporary directory change
|
||||
% The TestComponentInDir class defines a test component that has to be run by
|
||||
% first changing to a specified directory.
|
||||
%
|
||||
% The setUp method adds the starting directory to the path and then uses cd to
|
||||
% change into the specified directory. The tearDown method restores the
|
||||
% original path and directory.
|
||||
%
|
||||
% TestComponentInDir methods:
|
||||
% TestComponentInDir - Constructor
|
||||
% setUp - Add test directory to MATLAB path
|
||||
% tearDown - Restore original MATLAB path
|
||||
%
|
||||
% See also TestComponent
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
classdef TestComponentInDir < TestComponent
|
||||
properties (SetAccess = private, GetAccess = protected)
|
||||
%TestDirectory - Directory to change to in the test fixture
|
||||
TestDirectory
|
||||
|
||||
%OriginalPath - Path prior to adding the starting directory
|
||||
OriginalPath
|
||||
|
||||
%OriginalDirectory - Starting directory
|
||||
OriginalDirectory
|
||||
end
|
||||
|
||||
methods
|
||||
function self = TestComponentInDir(testDirectory)
|
||||
%TestCaseInDir Constructor
|
||||
% TestCaseInDir(testName, testDirectory) constructs a test case
|
||||
% using the specified name and located in the specified directory.
|
||||
self.TestDirectory = testDirectory;
|
||||
end
|
||||
|
||||
function setUp(self)
|
||||
%setUp Add test directory to MATLAB path
|
||||
% test_case.setUp() saves the current directory in the
|
||||
% OriginalDirectory property, saves the current path in the
|
||||
% OriginalPath property, and then uses cd to change into the test
|
||||
% directory.
|
||||
self.OriginalDirectory = pwd;
|
||||
self.OriginalPath = path;
|
||||
addpath(pwd);
|
||||
cd(self.TestDirectory);
|
||||
end
|
||||
|
||||
function tearDown(self)
|
||||
%tearDown Restore original MATLAB path and directory
|
||||
% test_case.tearDown() restores the original path and directory.
|
||||
cd(self.OriginalDirectory);
|
||||
path(self.OriginalPath);
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,258 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
%TestRunLogger Collect data (silently) from running test suite
|
||||
% TestRunLogger is a subclass of TestRunMonitor uses to collect information
|
||||
% from an executing test component (either a test case or a test suite).
|
||||
% It maintains a record of event notifications received, as well as any test
|
||||
% failures or test errors.
|
||||
%
|
||||
% TestRunLogger methods:
|
||||
% testComponentStarted - Log test component started
|
||||
% testComponentFinished - Log test component finished
|
||||
% testCaseFailure - Log test case failure
|
||||
% testCaseError - Log test case error
|
||||
%
|
||||
% TestRunLogger properties:
|
||||
% Log - Cell array of test notification strings
|
||||
% NumFailures - Number of test failures during execution
|
||||
% NumErrors - Number of test errors during execution
|
||||
% NumTestCases - Total number of test cases executed
|
||||
% Faults - Struct array of test fault information
|
||||
%
|
||||
% See also CommandWindowTestRunDisplay, TestRunMonitor, TestSuite
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
classdef TestRunLogger < TestRunMonitor
|
||||
|
||||
properties (SetAccess = protected)
|
||||
%Log Cell array of test notification strings
|
||||
% Test notification strings include 'TestRunStarted',
|
||||
% 'TestRunFinished', 'TestComponentStarted', 'TestComponentFinished',
|
||||
% 'TestCaseFailure', and 'TestCaseError'.
|
||||
Log
|
||||
|
||||
%NumFailures Number of test failures during execution
|
||||
NumFailures = 0
|
||||
|
||||
%NumErrors Number of test errors during execution
|
||||
NumErrors = 0
|
||||
|
||||
%NumTestCases Total number of test cases executed
|
||||
NumTestCases = 0
|
||||
|
||||
%Faults Struct array of test fault information
|
||||
% Faults is a struct array with the fields Type, TestCase, and
|
||||
% Exception. Type is either 'failure' or 'error'. TestCase is the
|
||||
% test case object that triggered the fault. Exception is the
|
||||
% MException object thrown during the fault.
|
||||
Faults = struct('Type', {}, 'TestCase', {}, 'Exception', {});
|
||||
end
|
||||
|
||||
properties (SetAccess = private, GetAccess = private)
|
||||
InitialTestComponent = []
|
||||
end
|
||||
|
||||
methods
|
||||
|
||||
function testComponentStarted(self, component)
|
||||
if isempty(self.InitialTestComponent)
|
||||
self.InitialTestComponent = component;
|
||||
self.appendToLog('TestRunStarted');
|
||||
end
|
||||
|
||||
self.appendToLog('TestComponentStarted');
|
||||
|
||||
if isa(component, 'TestCase')
|
||||
self.NumTestCases = self.NumTestCases + 1;
|
||||
end
|
||||
end
|
||||
|
||||
function testComponentFinished(self, component, did_pass)
|
||||
self.appendToLog('TestComponentFinished');
|
||||
|
||||
if isequal(component, self.InitialTestComponent)
|
||||
self.appendToLog('TestRunFinished');
|
||||
end
|
||||
end
|
||||
|
||||
function testCaseFailure(self, test_case, failure_exception)
|
||||
self.appendToLog('TestCaseFailure');
|
||||
self.NumFailures = self.NumFailures + 1;
|
||||
self.logFault('failure', test_case, ...
|
||||
failure_exception);
|
||||
end
|
||||
|
||||
function testCaseError(self, test_case, error_exception)
|
||||
self.appendToLog('TestCaseError');
|
||||
self.NumErrors = self.NumErrors + 1;
|
||||
self.logFault('error', test_case, ...
|
||||
error_exception);
|
||||
end
|
||||
end
|
||||
|
||||
methods (Access = private)
|
||||
function appendToLog(self, item)
|
||||
self.Log{end+1} = item;
|
||||
end
|
||||
|
||||
function logFault(self, type, test_case, exception)
|
||||
self.Faults(end + 1).Type = type;
|
||||
self.Faults(end).TestCase = test_case;
|
||||
self.Faults(end).Exception = exception;
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,35 +0,0 @@
|
|||
%TestRunMonitor Abstract base class for monitoring a running test suite
|
||||
% The abstract TestRunMonitor class defines an object that can observe and
|
||||
% record the results of running a test suite. The run() method of a
|
||||
% TestComponent object takes a TestRunMonitor object as an input argument.
|
||||
%
|
||||
% Different test suite logging or reporting functionality can be achieved by
|
||||
% subclassing TestRunMonitor. For example, see the TestRunLogger and the
|
||||
% CommandWindowTestRunDisplay classes.
|
||||
%
|
||||
% TestRunMonitor methods:
|
||||
% TestRunMonitor - Constructor
|
||||
% testComponentStarted - Called at beginning of test component run
|
||||
% testComponentFinished - Called when test component run finished
|
||||
% testCaseFailure - Called when a test case fails
|
||||
% testCaseError - Called when a test case causes an error
|
||||
%
|
||||
% See also CommandWindowTestRunDisplay, TestRunLogger, TestCase, TestSuite
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
classdef TestRunMonitor < handle
|
||||
|
||||
methods (Abstract)
|
||||
|
||||
testComponentStarted(self, component)
|
||||
|
||||
testComponentFinished(self, component, did_pass)
|
||||
|
||||
testCaseFailure(self, test_case, failure_exception)
|
||||
|
||||
testCaseError(self, test_case, error_exception)
|
||||
|
||||
end
|
||||
end
|
|
@ -1,342 +0,0 @@
|
|||
%TestSuite Collection of TestComponent objects
|
||||
% The TestSuite class defines a collection of TestComponent objects.
|
||||
%
|
||||
% TestSuite methods:
|
||||
% TestSuite - Constructor
|
||||
% add - Add test component to test suite
|
||||
% print - Display test suite summary to Command Window
|
||||
% run - Run the test suite
|
||||
% keepMatchingTestCase - Keep only the named test component
|
||||
% fromName - Construct test suite from directory or MATLAB function file name
|
||||
% fromTestCaseClassName - Construct test suite from TestCase class name
|
||||
% fromPackageName - Construct test suite from package name
|
||||
% fromPwd - Construct test suite from present directory
|
||||
%
|
||||
% TestSuite properties:
|
||||
% TestComponents - Cell array of TestComponent objects
|
||||
%
|
||||
% Examples
|
||||
% --------
|
||||
% Run all the test cases in the SampleTests1 class. Display test suite
|
||||
% progress and a summary of results in the Command Window.
|
||||
%
|
||||
% TestSuite('SampleTests1').run()
|
||||
%
|
||||
% Construct a test suite from all test components found in the current
|
||||
% directory.
|
||||
%
|
||||
% suite = TestSuite.fromPwd();
|
||||
%
|
||||
% Construct a test suite from all test components found in the package
|
||||
% 'mytool.tests'. (Note that the "+" character at the beginning of the package
|
||||
% folder name on disk is not part of the package name.)
|
||||
%
|
||||
% suite = TestSuite.fromPackageName('mytool.tests');
|
||||
%
|
||||
% Run all the test cases in the SampleTests class. Display no output to the
|
||||
% Command Window. Upon completion, query the number of test failures and test
|
||||
% errors.
|
||||
%
|
||||
% logger = TestRunLogger();
|
||||
% TestSuite('SampleTests1').run(logger);
|
||||
% numFailures = logger.NumFailures
|
||||
% numErrors = logger.NumErrors
|
||||
%
|
||||
% See also CommandWindowTestRunDisplay, TestCase, TestComponent, TestRunLogger
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
classdef TestSuite < TestComponent
|
||||
|
||||
properties (SetAccess = protected)
|
||||
TestComponents = {};
|
||||
end
|
||||
|
||||
methods
|
||||
|
||||
function self = TestSuite(name)
|
||||
%TestSuite Constructor
|
||||
% suite = TestSuite constructs an empty test suite. suite =
|
||||
% TestSuite(name) constructs a test suite by searching for test
|
||||
% cases defined in an M-file with the specified name.
|
||||
|
||||
if nargin >= 1
|
||||
self = TestSuite.fromName(name);
|
||||
end
|
||||
end
|
||||
|
||||
function did_pass_out = run(self, monitor)
|
||||
%run Execute test cases in test suite
|
||||
% did_pass = suite.run() executes all test cases in the test
|
||||
% suite, returning a logical value indicating whether or not all
|
||||
% test cases passed.
|
||||
|
||||
if nargin < 2
|
||||
monitor = CommandWindowTestRunDisplay();
|
||||
end
|
||||
|
||||
monitor.testComponentStarted(self);
|
||||
did_pass = true;
|
||||
|
||||
self.setUp();
|
||||
|
||||
for k = 1:numel(self.TestComponents)
|
||||
this_component_passed = self.TestComponents{k}.run(monitor);
|
||||
did_pass = did_pass && this_component_passed;
|
||||
end
|
||||
|
||||
self.tearDown();
|
||||
|
||||
monitor.testComponentFinished(self, did_pass);
|
||||
|
||||
if nargout > 0
|
||||
did_pass_out = did_pass;
|
||||
end
|
||||
end
|
||||
|
||||
function num = numTestCases(self)
|
||||
%numTestCases Number of test cases in test suite
|
||||
|
||||
num = 0;
|
||||
for k = 1:numel(self.TestComponents)
|
||||
component_k = self.TestComponents{k};
|
||||
num = num + component_k.numTestCases();
|
||||
end
|
||||
end
|
||||
|
||||
function print(self, numLeadingBlanks)
|
||||
%print Display test suite summary to Command Window
|
||||
% test_suite.print() displays a summary of the test suite to the
|
||||
% Command Window.
|
||||
|
||||
if nargin < 2
|
||||
numLeadingBlanks = 0;
|
||||
end
|
||||
fprintf('%s%s\n', blanks(numLeadingBlanks), self.Name);
|
||||
for k = 1:numel(self.TestComponents)
|
||||
self.TestComponents{k}.print(numLeadingBlanks + ...
|
||||
self.PrintIndentationSize);
|
||||
end
|
||||
end
|
||||
|
||||
function add(self, component)
|
||||
%add Add test component to test suite
|
||||
% test_suite.add(component) adds the TestComponent object to the
|
||||
% test suite.
|
||||
|
||||
if iscell(component)
|
||||
self.TestComponents((1:numel(component)) + end) = component;
|
||||
else
|
||||
self.TestComponents{end + 1} = component;
|
||||
end
|
||||
end
|
||||
|
||||
function keepMatchingTestCase(self, name)
|
||||
%keepMatchingTestCase Keep only the named test component
|
||||
% test_suite.keepMatchingTestCase(name) keeps only the test
|
||||
% component with a matching name and discards the rest.
|
||||
|
||||
idx = [];
|
||||
for k = 1:numel(self.TestComponents)
|
||||
if strcmp(self.TestComponents{k}.Name, name)
|
||||
idx = k;
|
||||
break;
|
||||
end
|
||||
end
|
||||
if isempty(idx)
|
||||
self.TestComponents = {};
|
||||
else
|
||||
self.TestComponents = self.TestComponents(idx);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Static)
|
||||
function suite = fromTestCaseClassName(class_name)
|
||||
%fromTestCaseClassName Construct test suite from TestCase class name
|
||||
% suite = TestSuite.fromTestCaseClassName(name) constructs a
|
||||
% TestSuite object from the name of a TestCase subclass.
|
||||
|
||||
if ~xunit.utils.isTestCaseSubclass(class_name)
|
||||
error('xunit:fromTestCaseClassName', ...
|
||||
'Input string "%s" is not the name of a TestCase class.', ...
|
||||
class_name);
|
||||
end
|
||||
|
||||
suite = TestSuite;
|
||||
suite.Name = class_name;
|
||||
suite.Location = which(class_name);
|
||||
|
||||
methods = getClassMethods(class_name);
|
||||
for k = 1:numel(methods)
|
||||
if methodIsConstructor(methods{k})
|
||||
continue
|
||||
end
|
||||
|
||||
method_name = methods{k}.Name;
|
||||
if xunit.utils.isTestString(method_name)
|
||||
suite.add(feval(class_name, method_name));
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function suite = fromName(name)
|
||||
%fromName Construct test suite from M-file name
|
||||
% test_suite = TestSuite.fromName(name) constructs a TestSuite
|
||||
% object from an M-file with the given name. The name can be of a
|
||||
% directory, a TestCase subclass, or an M-file containing a simple
|
||||
% test or containing subfunction-based tests.
|
||||
%
|
||||
% Optionally, name can contain a colon (':') followed by filter
|
||||
% string. The filter string is used to select a particular named
|
||||
% test case. For example, TestSuite.fromName('MyTests:testA')
|
||||
% constructs a TestSuite object containing only the test case
|
||||
% named 'testA' found in the TestCase subclass MyTests.
|
||||
|
||||
if isdir(name)
|
||||
suite = TestSuiteInDir(name);
|
||||
suite.gatherTestCases();
|
||||
return;
|
||||
end
|
||||
|
||||
[name, filter_string] = strtok(name, ':');
|
||||
if ~isempty(filter_string)
|
||||
filter_string = filter_string(2:end);
|
||||
end
|
||||
|
||||
if xunit.utils.isTestCaseSubclass(name)
|
||||
suite = TestSuite.fromTestCaseClassName(name);
|
||||
|
||||
elseif ~isempty(meta.class.fromName(name))
|
||||
% Input is the name of a class that is not a TestCase subclass.
|
||||
% Return an empty test suite.
|
||||
suite = TestSuite();
|
||||
suite.Name = name;
|
||||
|
||||
elseif isPackage(name)
|
||||
suite = TestSuite.fromPackageName(name);
|
||||
|
||||
else
|
||||
|
||||
try
|
||||
if nargout(name) == 0
|
||||
suite = TestSuite();
|
||||
suite.Name = name;
|
||||
suite.add(FunctionHandleTestCase(str2func(name), [], []));
|
||||
suite.Location = which(name);
|
||||
|
||||
else
|
||||
suite = feval(name);
|
||||
if ~isa(suite, 'TestSuite')
|
||||
error('Function did not return a TestSuite object.');
|
||||
end
|
||||
end
|
||||
|
||||
catch
|
||||
% Ordinary function does not appear to contain tests.
|
||||
% Return an empty test suite.
|
||||
suite = TestSuite();
|
||||
suite.Name = name;
|
||||
end
|
||||
end
|
||||
|
||||
if ~isempty(filter_string)
|
||||
suite.keepMatchingTestCase(filter_string);
|
||||
end
|
||||
end
|
||||
|
||||
function test_suite = fromPwd()
|
||||
%fromPwd Construct test suite from present directory
|
||||
% test_suite = TestSuite.fromPwd() constructs a TestSuite object
|
||||
% from all the test components in the present working directory.
|
||||
% all TestCase subclasses will be found, as well as simple and
|
||||
% subfunction-based M-file tests beginning with the string 'test'
|
||||
% or 'Test'.
|
||||
|
||||
test_suite = TestSuite();
|
||||
test_suite.Name = pwd;
|
||||
test_suite.Location = pwd;
|
||||
|
||||
mfiles = dir(fullfile('.', '*.m'));
|
||||
for k = 1:numel(mfiles)
|
||||
[path, name] = fileparts(mfiles(k).name);
|
||||
if xunit.utils.isTestCaseSubclass(name)
|
||||
test_suite.add(TestSuite.fromTestCaseClassName(name));
|
||||
elseif xunit.utils.isTestString(name)
|
||||
suite_k = TestSuite.fromName(name);
|
||||
if ~isempty(suite_k.TestComponents)
|
||||
test_suite.add(suite_k);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function test_suite = fromPackageName(name)
|
||||
%fromPackageName Construct test suite from package name
|
||||
% test_suite = TestSuite.fromPackageName(name) constructs a
|
||||
% TestSuite object from all the test components found in the
|
||||
% specified package.
|
||||
|
||||
package_info = meta.package.fromName(name);
|
||||
if isempty(package_info)
|
||||
error('xunit:fromPackageName:invalidName', ...
|
||||
'Input string "%s" is not the name of a package.', ...
|
||||
name);
|
||||
end
|
||||
test_suite = TestSuite();
|
||||
test_suite.Name = name;
|
||||
test_suite.Location = 'Package';
|
||||
|
||||
for k = 1:numel(package_info.Packages)
|
||||
pkg_name = package_info.Packages{k}.Name;
|
||||
pkg_suite = TestSuite.fromPackageName(pkg_name);
|
||||
if ~isempty(pkg_suite.TestComponents)
|
||||
test_suite.add(TestSuite.fromPackageName(pkg_name));
|
||||
end
|
||||
end
|
||||
|
||||
class_names = cell(1, numel(package_info.Classes));
|
||||
for k = 1:numel(package_info.Classes)
|
||||
class_name = package_info.Classes{k}.Name;
|
||||
class_names{k} = class_name;
|
||||
if xunit.utils.isTestCaseSubclass(class_name)
|
||||
test_suite.add(TestSuite.fromTestCaseClassName(class_name));
|
||||
end
|
||||
end
|
||||
|
||||
for k = 1:numel(package_info.Functions)
|
||||
function_name = package_info.Functions{k}.Name;
|
||||
if xunit.utils.isTestString(function_name)
|
||||
full_function_name = [package_info.Name '.' package_info.Functions{k}.Name];
|
||||
if ~ismember(full_function_name, class_names)
|
||||
suite_k = TestSuite.fromName(full_function_name);
|
||||
if ~isempty(suite_k.TestComponents)
|
||||
test_suite.add(suite_k);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tf = isPackage(name)
|
||||
tf = ~isempty(meta.package.fromName(name));
|
||||
end
|
||||
|
||||
function methods = getClassMethods(class_name)
|
||||
class_meta = meta.class.fromName(class_name);
|
||||
methods = class_meta.Methods;
|
||||
end
|
||||
|
||||
function result = methodIsConstructor(method)
|
||||
method_name = method.Name;
|
||||
if ~isempty(method.DefiningClass.ContainingPackage)
|
||||
method_name = [method.DefiningClass.ContainingPackage.Name, '.', ...
|
||||
method_name];
|
||||
end
|
||||
result = strcmp(method_name, method.DefiningClass.Name);
|
||||
end
|
|
@ -1,50 +0,0 @@
|
|||
%TestSuiteInDir Test suite requiring temporary directory change
|
||||
% The TestSuiteInDir class defines a test suite that has to be run by first
|
||||
% changing to a specified directory.
|
||||
%
|
||||
% The setUp method adds the starting directory to the path and then uses cd to
|
||||
% change into the specified directory. The tearDown method restores the
|
||||
% original path and directory.
|
||||
%
|
||||
% TestSuiteInDir methods:
|
||||
% TestSuiteInDir - Constructor
|
||||
% gatherTestCases - Add test cases found in the target directory
|
||||
%
|
||||
% See also TestSuite
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2009 The MathWorks, Inc.
|
||||
|
||||
classdef TestSuiteInDir < TestSuite & TestComponentInDir
|
||||
|
||||
methods
|
||||
function self = TestSuiteInDir(testDirectory)
|
||||
%TestCaseInDir Constructor
|
||||
% TestCaseInDir(testName, testDirectory) constructs a test case
|
||||
% using the specified name and located in the specified directory.
|
||||
self = self@TestComponentInDir(testDirectory);
|
||||
|
||||
if strcmp(testDirectory, '.')
|
||||
self.Name = pwd;
|
||||
self.Location = pwd;
|
||||
else
|
||||
[pathstr, name] = fileparts(testDirectory);
|
||||
self.Name = name;
|
||||
self.Location = testDirectory;
|
||||
end
|
||||
end
|
||||
|
||||
function gatherTestCases(self)
|
||||
%gatherTestCases Add test cases found in the target directory
|
||||
% suite.gatherTestCases() automaticall finds all the test cases in
|
||||
% the directory specified in the constructor call and adds them to
|
||||
% the suite.
|
||||
current_dir = pwd;
|
||||
c = onCleanup(@() cd(current_dir));
|
||||
|
||||
cd(self.TestDirectory);
|
||||
tmp = TestSuite.fromPwd();
|
||||
self.TestComponents = tmp.TestComponents;
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,112 +0,0 @@
|
|||
classdef VerboseTestRunDisplay < TestRunDisplay
|
||||
%VerboseTestRunDisplay Print test suite execution results.
|
||||
% VerboseTestRunDisplay is a subclass of
|
||||
% TestRunDisplay. It supports the -verbose option of runtests.
|
||||
%
|
||||
% Overriddent methods:
|
||||
% testComponentStarted - Update Command Window display
|
||||
% testComponentFinished - Update Command Window display
|
||||
% testRunFinished - Update Command Window display at end of run
|
||||
%
|
||||
% See also TestRunDisplay, TestRunLogger, TestRunMonitor, TestSuite
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2010 The MathWorks, Inc.
|
||||
|
||||
properties (SetAccess = private, GetAccess = private)
|
||||
TicStack = uint64([])
|
||||
end
|
||||
|
||||
methods
|
||||
function self = VerboseTestRunDisplay(output)
|
||||
if nargin < 1
|
||||
output = 1;
|
||||
end
|
||||
|
||||
self = self@TestRunDisplay(output);
|
||||
end
|
||||
|
||||
function testComponentStarted(self, component)
|
||||
%testComponentStarted Update Command Window display
|
||||
|
||||
self.pushTic();
|
||||
|
||||
if ~isa(component, 'TestCase')
|
||||
fprintf(self.FileHandle, '\n');
|
||||
end
|
||||
|
||||
fprintf(self.FileHandle, '%s%s', self.indentationSpaces(), component.Name);
|
||||
|
||||
if ~isa(component, 'TestCase')
|
||||
fprintf(self.FileHandle, '\n');
|
||||
else
|
||||
fprintf(self.FileHandle, ' %s ', self.leaderDots(component.Name));
|
||||
end
|
||||
end
|
||||
|
||||
function testComponentFinished(self, component, did_pass)
|
||||
%testComponentFinished Update Command Window display
|
||||
|
||||
if ~isa(component, 'TestCase')
|
||||
fprintf(self.FileHandle, '%s%s %s ', self.indentationSpaces(), component.Name, ...
|
||||
self.leaderDots(component.Name));
|
||||
end
|
||||
|
||||
component_run_time = toc(self.popTic());
|
||||
|
||||
if did_pass
|
||||
fprintf(self.FileHandle, 'passed in %12.6f seconds\n', component_run_time);
|
||||
else
|
||||
fprintf(self.FileHandle, 'FAILED in %12.6f seconds\n', component_run_time);
|
||||
end
|
||||
|
||||
if ~isa(component, 'TestCase')
|
||||
fprintf(self.FileHandle, '\n');
|
||||
end
|
||||
|
||||
if isempty(self.TicStack)
|
||||
self.testRunFinished();
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Access = protected)
|
||||
function testRunFinished(self)
|
||||
%testRunFinished Update Command Window display
|
||||
% obj.testRunFinished(component) displays information about the test
|
||||
% run results, including any test failures, to the Command
|
||||
% Window.
|
||||
|
||||
self.displayFaults();
|
||||
end
|
||||
end
|
||||
|
||||
methods (Access = private)
|
||||
function pushTic(self)
|
||||
self.TicStack(end+1) = tic;
|
||||
end
|
||||
|
||||
function t1 = popTic(self)
|
||||
t1 = self.TicStack(end);
|
||||
self.TicStack(end) = [];
|
||||
end
|
||||
|
||||
function str = indentationSpaces(self)
|
||||
str = repmat(' ', 1, self.numIndentationSpaces());
|
||||
end
|
||||
|
||||
function n = numIndentationSpaces(self)
|
||||
indent_level = numel(self.TicStack) - 1;
|
||||
n = 3 * indent_level;
|
||||
end
|
||||
|
||||
function str = leaderDots(self, name)
|
||||
num_dots = max(0, 40 - self.numIndentationSpaces() - numel(name));
|
||||
str = repmat('.', 1, num_dots);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,52 +0,0 @@
|
|||
function assertAlmostEqual(A, B, reltol, message)
|
||||
%assertEqual Assert that inputs are equal within relative tolerance
|
||||
% assertEqual(A, B, RELTOL) throws an exception of any of the values in A and
|
||||
% B are not equal within the specified tolerance. NaN values are considered
|
||||
% to be equal. A and B have to have the same class and sparsity to be
|
||||
% considered equal.
|
||||
%
|
||||
% assertEqual(A, B) uses the following relative tolerance value:
|
||||
%
|
||||
% 100 * eps(class(A))
|
||||
%
|
||||
% assertEqual(A, B, RELTOL, MESSAGE) uses the specified message string when
|
||||
% throwing the exception. With this syntax, use RELTOL = [] to specify the
|
||||
% default relative tolerance.
|
||||
%
|
||||
% Note that if either A or B are not floating-point arrays, then A and B are
|
||||
% compared using ISEQUALWITHEQUALNANS and the relative tolerance value is not
|
||||
% used.
|
||||
%
|
||||
% Examples
|
||||
% --------
|
||||
% % This call returns silently.
|
||||
% assertAlmostEqual(1.0, 1.0 + eps);
|
||||
%
|
||||
% % This call throws an error.
|
||||
% assertAlmostEqual(1.0, 1.1);
|
||||
%
|
||||
% See also assertEqual, mtest.utils.isAlmostEqual
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
if ~(issparse(A) == issparse(B))
|
||||
throw(MException('assertAlmostEqual:sparsityNotEqual', message));
|
||||
end
|
||||
|
||||
if ~strcmp(class(A), class(B))
|
||||
throw(MException('assertAlmostEqual:classNotEqual', message));
|
||||
end
|
||||
|
||||
if nargin < 3 || isempty(reltol)
|
||||
reltol = 100 * eps(class(A));
|
||||
end
|
||||
|
||||
if nargin < 4
|
||||
message = sprintf('Inputs are not equal within relative tolerance: %g', ...
|
||||
reltol);
|
||||
end
|
||||
|
||||
if ~xunit.utils.isAlmostEqual(A, B, reltol)
|
||||
throw(MException('assertAlmostEqual:tolExceeded', message));
|
||||
end
|
|
@ -1,61 +0,0 @@
|
|||
function assertElementsAlmostEqual(varargin)
|
||||
%assertElementsAlmostEqual Assert floating-point array elements almost equal.
|
||||
% assertElementsAlmostEqual(A, B, tol_type, tol, floor_tol) asserts that all
|
||||
% elements of floating-point arrays A and B are equal within some tolerance.
|
||||
% tol_type can be 'relative' or 'absolute'. tol and floor_tol are scalar
|
||||
% tolerance values.
|
||||
%
|
||||
% If the tolerance type is 'relative', then the tolerance test used is:
|
||||
%
|
||||
% all( abs(A(:) - B(:)) <= tol * max(abs(A(:)), abs(B(:))) + floor_tol )
|
||||
%
|
||||
% If the tolerance type is 'absolute', then the tolerance test used is:
|
||||
%
|
||||
% all( abs(A(:) - B(:)) <= tol )
|
||||
%
|
||||
% tol_type, tol, and floor_tol are all optional. The default value for
|
||||
% tol_type is 'relative'. If both A and B are double, then the default value
|
||||
% for tol and floor_tol is sqrt(eps). If either A or B is single, then the
|
||||
% default value for tol and floor_tol is sqrt(eps('single')).
|
||||
%
|
||||
% If A or B is complex, then the tolerance test is applied independently to
|
||||
% the real and imaginary parts.
|
||||
%
|
||||
% Corresponding elements in A and B that are both NaN, or are both infinite
|
||||
% with the same sign, are considered to pass the tolerance test.
|
||||
%
|
||||
% assertElementsAlmostEqual(A, B, ..., msg) prepends the string msg to the
|
||||
% output message if A and B fail the tolerance test.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
params = xunit.utils.parseFloatAssertInputs(varargin{:});
|
||||
|
||||
if ~isequal(size(params.A), size(params.B))
|
||||
message = xunit.utils.comparisonMessage(params.Message, ...
|
||||
'Inputs are not the same size.', ...
|
||||
params.A, params.B);
|
||||
throwAsCaller(MException('assertElementsAlmostEqual:sizeMismatch', ...
|
||||
'%s', message));
|
||||
end
|
||||
|
||||
if ~(isfloat(params.A) && isfloat(params.B))
|
||||
message = xunit.utils.comparisonMessage(params.Message, ...
|
||||
'Inputs are not both floating-point.', ...
|
||||
params.A, params.B);
|
||||
throwAsCaller(MException('assertElementsAlmostEqual:notFloat', ...
|
||||
'%s', message));
|
||||
end
|
||||
|
||||
if ~xunit.utils.compareFloats(params.A, params.B, 'elementwise', ...
|
||||
params.ToleranceType, params.Tolerance, params.FloorTolerance)
|
||||
|
||||
tolerance_message = sprintf('Input elements are not all equal within %s tolerance: %g', ...
|
||||
params.ToleranceType, params.Tolerance);
|
||||
message = xunit.utils.comparisonMessage(params.Message, tolerance_message, ...
|
||||
params.A, params.B);
|
||||
|
||||
throwAsCaller(MException('assertElementsAlmostEqual:tolExceeded', ...
|
||||
'%s', message));
|
||||
end
|
|
@ -1,43 +0,0 @@
|
|||
function assertEqual(A, B, custom_message)
|
||||
%assertEqual Assert that inputs are equal
|
||||
% assertEqual(A, B) throws an exception if A and B are not equal. A and B
|
||||
% must have the same class and sparsity to be considered equal.
|
||||
%
|
||||
% assertEqual(A, B, MESSAGE) prepends the string MESSAGE to the assertion
|
||||
% message if A and B are not equal.
|
||||
%
|
||||
% Examples
|
||||
% --------
|
||||
% % This call returns silently.
|
||||
% assertEqual([1 NaN 2], [1 NaN 2]);
|
||||
%
|
||||
% % This call throws an error.
|
||||
% assertEqual({'A', 'B', 'C'}, {'A', 'foo', 'C'});
|
||||
%
|
||||
% See also assertElementsAlmostEqual, assertVectorsAlmostEqual
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
if nargin < 3
|
||||
custom_message = '';
|
||||
end
|
||||
|
||||
if ~ (issparse(A) == issparse(B))
|
||||
message = xunit.utils.comparisonMessage(custom_message, ...
|
||||
'One input is sparse and the other is not.', A, B);
|
||||
throwAsCaller(MException('assertEqual:sparsityNotEqual', '%s', message));
|
||||
end
|
||||
|
||||
if ~strcmp(class(A), class(B))
|
||||
message = xunit.utils.comparisonMessage(custom_message, ...
|
||||
'The inputs differ in class.', A, B);
|
||||
throwAsCaller(MException('assertEqual:classNotEqual', '%s', message));
|
||||
end
|
||||
|
||||
if ~isequalwithequalnans(A, B)
|
||||
message = xunit.utils.comparisonMessage(custom_message, ...
|
||||
'Inputs are not equal.', A, B);
|
||||
throwAsCaller(MException('assertEqual:nonEqual', '%s', message));
|
||||
end
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
function assertExceptionThrown(f, expectedId, custom_message)
|
||||
%assertExceptionThrown Assert that specified exception is thrown
|
||||
% assertExceptionThrown(F, expectedId) calls the function handle F with no
|
||||
% input arguments. If the result is a thrown exception whose identifier is
|
||||
% expectedId, then assertExceptionThrown returns silently. If no exception is
|
||||
% thrown, then assertExceptionThrown throws an exception with identifier equal
|
||||
% to 'assertExceptionThrown:noException'. If a different exception is thrown,
|
||||
% then assertExceptionThrown throws an exception identifier equal to
|
||||
% 'assertExceptionThrown:wrongException'.
|
||||
%
|
||||
% assertExceptionThrown(F, expectedId, msg) prepends the string msg to the
|
||||
% assertion message.
|
||||
%
|
||||
% Example
|
||||
% -------
|
||||
% % This call returns silently.
|
||||
% f = @() error('a:b:c', 'error message');
|
||||
% assertExceptionThrown(f, 'a:b:c');
|
||||
%
|
||||
% % This call returns silently.
|
||||
% assertExceptionThrown(@() sin, 'MATLAB:minrhs');
|
||||
%
|
||||
% % This call throws an error because calling sin(pi) does not error.
|
||||
% assertExceptionThrown(@() sin(pi), 'MATLAB:foo');
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
noException = false;
|
||||
try
|
||||
f();
|
||||
noException = true;
|
||||
|
||||
catch exception
|
||||
if ~strcmp(exception.identifier, expectedId)
|
||||
message = sprintf('Expected exception %s but got exception %s.', ...
|
||||
expectedId, exception.identifier);
|
||||
if nargin >= 3
|
||||
message = sprintf('%s\n%s', custom_message, message);
|
||||
end
|
||||
throwAsCaller(MException('assertExceptionThrown:wrongException', ...
|
||||
'%s', message));
|
||||
end
|
||||
end
|
||||
|
||||
if noException
|
||||
message = sprintf('Expected exception "%s", but none thrown.', ...
|
||||
expectedId);
|
||||
if nargin >= 3
|
||||
message = sprintf('%s\n%s', custom_message, message);
|
||||
end
|
||||
throwAsCaller(MException('assertExceptionThrown:noException', '%s', message));
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
function assertFalse(condition, message)
|
||||
%assertFalse Assert that input condition is false
|
||||
% assertFalse(CONDITION, MESSAGE) throws an exception containing the string
|
||||
% MESSAGE if CONDITION is not false.
|
||||
%
|
||||
% MESSAGE is optional.
|
||||
%
|
||||
% Examples
|
||||
% --------
|
||||
% assertFalse(isreal(sqrt(-1)))
|
||||
%
|
||||
% assertFalse(isreal(sqrt(-1)), ...
|
||||
% 'Expected isreal(sqrt(-1)) to be false.')
|
||||
%
|
||||
% See also assertTrue
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
if nargin < 2
|
||||
message = 'Asserted condition is not false.';
|
||||
end
|
||||
|
||||
if ~isscalar(condition) || ~islogical(condition)
|
||||
throwAsCaller(MException('assertFalse:invalidCondition', ...
|
||||
'CONDITION must be a scalar logical value.'));
|
||||
end
|
||||
|
||||
if condition
|
||||
throwAsCaller(MException('assertFalse:trueCondition', '%s', message));
|
||||
end
|
|
@ -1,68 +0,0 @@
|
|||
function assertFilesEqual(filename1, filename2, user_message)
|
||||
%assertFilesEqual Assert that files contain the same contents.
|
||||
% assertFilesEqual(filename1, filename2) throws an exception if the two
|
||||
% specified files do not contain the same contents.
|
||||
%
|
||||
% assertFilesEqual(filename1, filename2, message) prepends the specified
|
||||
% message string to the assertion message.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2009-2010 The MathWorks, Inc.
|
||||
|
||||
if nargin < 3
|
||||
user_message = '';
|
||||
end
|
||||
|
||||
fid1 = fopen(filename1, 'r');
|
||||
if (fid1 < 0)
|
||||
message = sprintf('%s\nCould not open file for reading: %s', ...
|
||||
user_message, filename1);
|
||||
throwAsCaller(MException('assertFilesEqual:readFailure', ...
|
||||
'%s', message));
|
||||
else
|
||||
c1 = onCleanup(@() fclose(fid1));
|
||||
end
|
||||
|
||||
fid2 = fopen(filename2, 'r');
|
||||
if (fid2 < 0)
|
||||
message = sprintf('%s\nCould not open file for reading: %s', ...
|
||||
user_message, filename2);
|
||||
throwAsCaller(MException('assertFilesEqual:readFailure', '%s', message));
|
||||
else
|
||||
c2 = onCleanup(@() fclose(fid2));
|
||||
end
|
||||
|
||||
block_size = 100000;
|
||||
num_blocks = 0;
|
||||
done = false;
|
||||
while ~done
|
||||
block_from_file1 = fread(fid1, block_size, '*uint8');
|
||||
block_from_file2 = fread(fid2, block_size, '*uint8');
|
||||
|
||||
if numel(block_from_file1) ~= numel(block_from_file2)
|
||||
fseek(fid1, 0, 'eof');
|
||||
fseek(fid2, 0, 'eof');
|
||||
message = sprintf('The two files are not the same size. File "%s" has %d bytes and file "%s" has %d bytes', ...
|
||||
filename1, ftell(fid1), filename2, ftell(fid2));
|
||||
if ~isempty(user_message)
|
||||
message = sprintf('%s\n%s', user_message, message);
|
||||
end
|
||||
throwAsCaller(MException('assertFilesEqual:sizeMismatch', '%s', message));
|
||||
end
|
||||
|
||||
if ~isequal(block_from_file1, block_from_file2)
|
||||
first_difference_in_block = find(block_from_file1 ~= block_from_file2);
|
||||
first_difference = num_blocks * block_size + first_difference_in_block;
|
||||
|
||||
message = sprintf('Files are not equal. First difference is at byte %d, where file "%s" contains 0x%X and file "%s" contains 0x%X', ...
|
||||
first_difference, filename1, block_from_file1(first_difference_in_block), ...
|
||||
filename2, block_from_file2(first_difference_in_block));
|
||||
if ~isempty(user_message)
|
||||
message = sprintf('%s\n%s', user_message, message);
|
||||
end
|
||||
throwAsCaller(MException('assertFilesEqual:valuesDiffer', '%s', message));
|
||||
end
|
||||
|
||||
done = numel(block_from_file1) < block_size;
|
||||
num_blocks = num_blocks + 1;
|
||||
end
|
|
@ -1,33 +0,0 @@
|
|||
function assertTrue(condition, message)
|
||||
%assertTrue Assert that input condition is true
|
||||
% assertTrue(CONDITION, MESSAGE) throws an exception containing the string
|
||||
% MESSAGE if CONDITION is not true.
|
||||
%
|
||||
% MESSAGE is optional.
|
||||
%
|
||||
% Examples
|
||||
% --------
|
||||
% % This call returns silently.
|
||||
% assertTrue(rand < 1, 'Expected output of rand to be less than 1')
|
||||
%
|
||||
% % This call throws an error.
|
||||
% assertTrue(sum(sum(magic(3))) == 0, ...
|
||||
% 'Expected sum of elements of magic(3) to be 0')
|
||||
%
|
||||
% See also assertEqual, assertFalse
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
if nargin < 2
|
||||
message = 'Asserted condition is not true.';
|
||||
end
|
||||
|
||||
if ~isscalar(condition) || ~islogical(condition)
|
||||
throwAsCaller(MException('assertTrue:invalidCondition', ...
|
||||
'CONDITION must be a scalar logical value.'));
|
||||
end
|
||||
|
||||
if ~condition
|
||||
throwAsCaller(MException('assertTrue:falseCondition', '%s', message));
|
||||
end
|
|
@ -1,59 +0,0 @@
|
|||
function assertVectorsAlmostEqual(varargin)
|
||||
%assertVectorsAlmostEqual Assert floating-point vectors almost equal in norm sense.
|
||||
% assertVectorsAlmostEqual(A, B, tol_type, tol, floor_tol) asserts that the
|
||||
% vectors A and B are equal, in the L2-norm sense and within some tolerance.
|
||||
% tol_type can be 'relative' or 'absolute'. tol and floor_tol are scalar
|
||||
% tolerance values.
|
||||
%
|
||||
% If the tolerance type is 'relative', then the tolerance test used is:
|
||||
%
|
||||
% all( norm(A - B) <= tol * max(norm(A), norm(B)) + floor_tol )
|
||||
%
|
||||
% If the tolerance type is 'absolute', then the tolerance test used is:
|
||||
%
|
||||
% all( norm(A - B) <= tol )
|
||||
%
|
||||
% tol_type, tol, and floor_tol are all optional. The default value for
|
||||
% tol_type is 'relative'. If both A and B are double, then the default value
|
||||
% for tol and floor_tol is sqrt(eps). If either A or B is single, then the
|
||||
% default value for tol and floor_tol is sqrt(eps('single')).
|
||||
%
|
||||
% If A or B is complex, then the tolerance test is applied independently to
|
||||
% the real and imaginary parts.
|
||||
%
|
||||
% Any infinite or NaN element of A or B will cause an assertion failure.
|
||||
%
|
||||
% assertVectorsAlmostEqual(A, B, ..., msg) prepends the string msg to the
|
||||
% assertion message if A and B fail the tolerance test.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2010 The MathWorks, Inc.
|
||||
|
||||
params = xunit.utils.parseFloatAssertInputs(varargin{:});
|
||||
|
||||
if ~isequal(size(params.A), size(params.B))
|
||||
message = xunit.utils.comparisonMessage(params.Message, ...
|
||||
'Inputs are not the same size.', ...
|
||||
params.A, params.B);
|
||||
throwAsCaller(MException('assertVectorsAlmostEqual:sizeMismatch', ...
|
||||
'%s', message));
|
||||
end
|
||||
|
||||
if ~(isfloat(params.A) && isfloat(params.B))
|
||||
message = xunit.utils.comparisonMessage(params.Message, ...
|
||||
'Inputs are not both floating-point.', ...
|
||||
params.A, params.B);
|
||||
throwAsCaller(MException('assertVectorsAlmostEqual:notFloat', ...
|
||||
'%s', message));
|
||||
end
|
||||
|
||||
if ~xunit.utils.compareFloats(params.A, params.B, 'vector', ...
|
||||
params.ToleranceType, params.Tolerance, params.FloorTolerance)
|
||||
|
||||
tolerance_message = sprintf('Inputs are not equal within %s vector tolerance: %g', ...
|
||||
params.ToleranceType, params.Tolerance);
|
||||
message = xunit.utils.comparisonMessage(params.Message, tolerance_message, ...
|
||||
params.A, params.B);
|
||||
throwAsCaller(MException('assertVectorsAlmostEqual:tolExceeded', ...
|
||||
'%s', message));
|
||||
end
|
|
@ -1,28 +0,0 @@
|
|||
<productinfo
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="optional">
|
||||
<?xml-stylesheet type="text/xsl" href="optional"?>
|
||||
|
||||
<matlabrelease>R2009a</matlabrelease>
|
||||
<name>MATLAB xUnit Test Framework</name>
|
||||
<type>Other</type>
|
||||
<icon>$toolbox/matlab/icons/matlabicon.gif</icon>
|
||||
<help_location>../doc/</help_location>
|
||||
|
||||
<list>
|
||||
|
||||
<listitem>
|
||||
<label>Help</label>
|
||||
<callback>doc xunit</callback>
|
||||
<icon>$toolbox/matlab/icons/book_mat.gif</icon>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<label>Web Page (File Exchange)</label>
|
||||
<callback>web http://www.mathworks.com/matlabcentral/fileexchange/22846 -browser;</callback>
|
||||
<icon>$toolbox/matlab/icons/webicon.gif</icon>
|
||||
</listitem>
|
||||
|
||||
</list>
|
||||
|
||||
</productinfo>
|
|
@ -1,58 +0,0 @@
|
|||
%findSubfunctionTests Utility script used for subfunction-based tests
|
||||
% This file is a script that is called at the top of M-files containing
|
||||
% subfunction-based tests.
|
||||
%
|
||||
% The top of a typical M-file using this script looks like this:
|
||||
%
|
||||
% function test_suite = testFeatureA
|
||||
%
|
||||
% findSubfunctionTests;
|
||||
%
|
||||
% IMPORTANT NOTE
|
||||
% --------------
|
||||
% The output variable name for an M-file using this script must be test_suite.
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2008-2009 The MathWorks, Inc.
|
||||
|
||||
[ST,I] = dbstack('-completenames');
|
||||
caller_name = ST(I + 1).name;
|
||||
caller_file = ST(I + 1).file;
|
||||
subFcns = which('-subfun', caller_file);
|
||||
|
||||
setup_fcn_name = subFcns(xunit.utils.isSetUpString(subFcns));
|
||||
if numel(setup_fcn_name) > 1
|
||||
error('findSubfunctionTests:tooManySetupFcns', ...
|
||||
'Found more than one setup subfunction.')
|
||||
elseif isempty(setup_fcn_name)
|
||||
setup_fcn = [];
|
||||
else
|
||||
setup_fcn = str2func(setup_fcn_name{1});
|
||||
end
|
||||
|
||||
teardown_fcn_name = subFcns(xunit.utils.isTearDownString(subFcns));
|
||||
if numel(teardown_fcn_name) > 1
|
||||
error('findSubfunctionTests:tooManyTeardownFcns', ...
|
||||
'Found more than one teardown subfunction.')
|
||||
elseif isempty(teardown_fcn_name)
|
||||
teardown_fcn = [];
|
||||
else
|
||||
teardown_fcn = str2func(teardown_fcn_name{1});
|
||||
end
|
||||
|
||||
test_fcns = cellfun(@str2func, subFcns(xunit.utils.isTestString(subFcns)), ...
|
||||
'UniformOutput', false);
|
||||
|
||||
suite = TestSuite;
|
||||
suite.Name = caller_name;
|
||||
suite.Location = which(caller_file);
|
||||
for k = 1:numel(test_fcns)
|
||||
suite.add(FunctionHandleTestCase(test_fcns{k}, setup_fcn, teardown_fcn));
|
||||
end
|
||||
|
||||
if nargout > 0
|
||||
test_suite = suite;
|
||||
else
|
||||
suite.run();
|
||||
end
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
Copyright (c) 2010, The MathWorks, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution
|
||||
* Neither the name of the The MathWorks, Inc. nor the names
|
||||
of its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,160 +0,0 @@
|
|||
function out = runtests(varargin)
|
||||
%runtests Run unit tests
|
||||
% runtests runs all the test cases that can be found in the current directory
|
||||
% and summarizes the results in the Command Window.
|
||||
%
|
||||
% Test cases can be found in the following places in the current directory:
|
||||
%
|
||||
% * An M-file function whose name starts or ends with "test" or
|
||||
% "Test" and that returns no output arguments.
|
||||
%
|
||||
% * An M-file function whose name starts or ends with "test" or
|
||||
% "Test" and that contains subfunction tests and uses the
|
||||
% initTestSuite script to return a TestSuite object.
|
||||
%
|
||||
% * An M-file defining a subclass of TestCase.
|
||||
%
|
||||
% runtests(dirname) runs all the test cases found in the specified directory.
|
||||
%
|
||||
% runtests(packagename) runs all the test cases found in the specified
|
||||
% package. (This option requires R2009a or later).
|
||||
%
|
||||
% runtests(mfilename) runs test cases found in the specified function or class
|
||||
% name. The function or class needs to be in the current directory or on the
|
||||
% MATLAB path.
|
||||
%
|
||||
% runtests('mfilename:testname') runs the specific test case named 'testname'
|
||||
% found in the function or class 'name'.
|
||||
%
|
||||
% Multiple directories or file names can be specified by passing multiple
|
||||
% names to runtests, as in runtests(name1, name2, ...) or
|
||||
% runtests({name1, name2, ...}, ...)
|
||||
%
|
||||
% runtests(..., '-verbose') displays the name and result, result, and time
|
||||
% taken for each test case to the Command Window.
|
||||
%
|
||||
% runtests(..., '-logfile', filename) directs the output of runtests to
|
||||
% the specified log file instead of to the Command Window.
|
||||
%
|
||||
% out = runtests(...) returns a logical value that is true if all the
|
||||
% tests passed.
|
||||
%
|
||||
% Examples
|
||||
% --------
|
||||
% Find and run all the test cases in the current directory.
|
||||
%
|
||||
% runtests
|
||||
%
|
||||
% Find and run all the test cases in the current directory. Display more
|
||||
% detailed information to the Command Window as the test cases are run.
|
||||
%
|
||||
% runtests -verbose
|
||||
%
|
||||
% Save verbose runtests output to a log file.
|
||||
%
|
||||
% runtests -verbose -logfile my_test_log.txt
|
||||
%
|
||||
% Find and run all the test cases contained in the M-file myfunc.
|
||||
%
|
||||
% runtests myfunc
|
||||
%
|
||||
% Find and run all the test cases contained in the TestCase subclass
|
||||
% MyTestCase.
|
||||
%
|
||||
% runtests MyTestCase
|
||||
%
|
||||
% Run the test case named 'testFeature' contained in the M-file myfunc.
|
||||
%
|
||||
% runtests myfunc:testFeature
|
||||
%
|
||||
% Run all the tests in a specific directory.
|
||||
%
|
||||
% runtests c:\Work\MyProject\tests
|
||||
%
|
||||
% Run all the tests in two directories.
|
||||
%
|
||||
% runtests c:\Work\MyProject\tests c:\Work\Book\tests
|
||||
|
||||
% Steven L. Eddins
|
||||
% Copyright 2009-2010 The MathWorks, Inc.
|
||||
|
||||
verbose = false;
|
||||
logfile = '';
|
||||
if nargin < 1
|
||||
suite = TestSuite.fromPwd();
|
||||
else
|
||||
[name_list, verbose, logfile] = getInputNames(varargin{:});
|
||||
if numel(name_list) == 0
|
||||
suite = TestSuite.fromPwd();
|
||||
elseif numel(name_list) == 1
|
||||
suite = TestSuite.fromName(name_list{1});
|
||||
else
|
||||
suite = TestSuite();
|
||||
for k = 1:numel(name_list)
|
||||
suite.add(TestSuite.fromName(name_list{k}));
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isempty(suite.TestComponents)
|
||||
error('xunit:runtests:noTestCasesFound', 'No test cases found.');
|
||||
end
|
||||
|
||||
if isempty(logfile)
|
||||
logfile_handle = 1; % File handle corresponding to Command Window
|
||||
else
|
||||
logfile_handle = fopen(logfile, 'w');
|
||||
if logfile_handle < 0
|
||||
error('xunit:runtests:FileOpenFailed', ...
|
||||
'Could not open "%s" for writing.', logfile);
|
||||
else
|
||||
cleanup = onCleanup(@() fclose(logfile_handle));
|
||||
end
|
||||
end
|
||||
|
||||
fprintf(logfile_handle, 'Test suite: %s\n', suite.Name);
|
||||
if ~strcmp(suite.Name, suite.Location)
|
||||
fprintf(logfile_handle, 'Test suite location: %s\n', suite.Location);
|
||||
end
|
||||
fprintf(logfile_handle, '%s\n\n', datestr(now));
|
||||
|
||||
if verbose
|
||||
monitor = VerboseTestRunDisplay(logfile_handle);
|
||||
else
|
||||
monitor = TestRunDisplay(logfile_handle);
|
||||
end
|
||||
did_pass = suite.run(monitor);
|
||||
|
||||
if nargout > 0
|
||||
out = did_pass;
|
||||
end
|
||||
|
||||
function [name_list, verbose, logfile] = getInputNames(varargin)
|
||||
name_list = {};
|
||||
verbose = false;
|
||||
logfile = '';
|
||||
k = 1;
|
||||
while k <= numel(varargin)
|
||||
arg = varargin{k};
|
||||
if iscell(arg)
|
||||
name_list = [name_list; arg];
|
||||
elseif ~isempty(arg) && (arg(1) == '-')
|
||||
if strcmp(arg, '-verbose')
|
||||
verbose = true;
|
||||
elseif strcmp(arg, '-logfile')
|
||||
if k == numel(varargin)
|
||||
error('xunit:runtests:MissingLogfile', ...
|
||||
'The option -logfile must be followed by a filename.');
|
||||
else
|
||||
logfile = varargin{k+1};
|
||||
k = k + 1;
|
||||
end
|
||||
else
|
||||
warning('runtests:unrecognizedOption', 'Unrecognized option: %s', arg);
|
||||
end
|
||||
else
|
||||
name_list{end+1} = arg;
|
||||
end
|
||||
k = k + 1;
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user