[MATLAB-legacy] Remove ext/matlab_xunit

This commit is contained in:
Ingmar Schoegl 2024-02-20 18:24:06 -06:00 committed by Ray Speth
parent 5e275fc63d
commit 5b8a0a4ecc
40 changed files with 0 additions and 2603 deletions

View File

@ -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.

View File

@ -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));

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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.

View File

@ -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