Skip to content

Commit 545bcb0

Browse files
committed
Initial commit from version 3.0.2 of xUnit, from File Exchange
0 parents  commit 545bcb0

File tree

168 files changed

+8291
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

168 files changed

+8291
-0
lines changed

Readme.html

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<html>
2+
<head>
3+
<meta http-equiv="REFRESH" content="0;url=doc/xunit_product_page.html">
4+
</head>
5+
<body>
6+
</body>
7+
</html>

architecture/class_diagram_a.vsd

133 KB
Binary file not shown.

architecture/class_diagram_b.vsd

129 KB
Binary file not shown.

architecture/class_diagram_c.vsd

132 KB
Binary file not shown.

architecture/html/class_diagram_a.gif

7.46 KB
Loading

architecture/html/class_diagram_b.gif

4.03 KB
Loading

architecture/html/class_diagram_c.gif

9.5 KB
Loading

architecture/html/matlab_xunit_architecture.html

+652
Large diffs are not rendered by default.
+344
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
%% MATLAB xUnit Test Framework: Architectural Notes
2+
% This document summarizes the key classes and design choices for MATLAB xUnit,
3+
% a MATLAB unit testing framework based on xUnit patterns.
4+
%
5+
% Note: Testing pattern and smell terminology in this document is drawn from
6+
% _xUnit Test Patterns: Refactoring Test Code_, by Gerard Meszaros,
7+
% Addison-Wesley, 2007.
8+
9+
%% TestComponent, TestCase, and TestSuite
10+
%
11+
% <<class_diagram_a.gif>>
12+
%
13+
% The abstract |TestComponent| class defines an object that has a description (a
14+
% name and a location) and that can be run.
15+
%
16+
% A |TestCase| object is a test component that defines an individual test case
17+
% that can be run with a pass or fail result.
18+
%
19+
% A |TestSuite| object is a test component that contains a collection of other
20+
% test components. Note the hierarchical nature of test suites; they can
21+
% contain both individual test case objects as well as other test suites.
22+
% Running a test suite means invoking the |run| method on each test component in
23+
% its collection.
24+
25+
%% TestCase: The Four-Phase Test
26+
%
27+
% The TestCase class provides the standard xUnit _Four-Phase Test_, using
28+
% a _Fresh Fixture_, _Implicit Setup_, and _Implicit Teardown_. These all
29+
% elements can all be seen in the |run| method of TestCase:
30+
%
31+
% function did_pass = run(self, monitor)
32+
% %run Execute the test case
33+
% % test_case.run(monitor) calls the TestCase object's setUp()
34+
% % method, then the test method, then the tearDown() method.
35+
% % observer is a TestRunObserver object. The testStarted(),
36+
% % testFailure(), testError(), and testFinished() methods of
37+
% % observer are called at the appropriate times. monitor is a
38+
% % TestRunMonitor object. Typically it is either a TestRunLogger
39+
% % subclass or a CommandWindowTestRunDisplay subclass.
40+
% %
41+
% % test_case.run() automatically uses a
42+
% % CommandWindowTestRunDisplay object in order to print test
43+
% % suite execution information to the Command Window.
44+
%
45+
% if nargin < 2
46+
% monitor = CommandWindowTestRunDisplay();
47+
% end
48+
%
49+
% did_pass = true;
50+
% monitor.testComponentStarted(self);
51+
%
52+
% try
53+
% self.setUp();
54+
% f = str2func(self.MethodName);
55+
%
56+
% try
57+
% % Call the test method.
58+
% f(self);
59+
% catch failureException
60+
% monitor.testCaseFailure(self, failureException);
61+
% did_pass = false;
62+
% end
63+
%
64+
% self.tearDown();
65+
%
66+
% catch errorException
67+
% monitor.testCaseError(self, errorException);
68+
% did_pass = false;
69+
% end
70+
%
71+
% monitor.testComponentFinished(self, did_pass);
72+
% end
73+
%
74+
% Phase 1 sets up the test fixture via the _Implicit Setup_ call, |self.setUp()|.
75+
% The base class |setUp()| method does nothing.
76+
%
77+
% Phases 2 and 3 (exercising the system under test and verifying the expected
78+
% outcome) are handled by the test method, which is invoked by |f(self)|.
79+
%
80+
% Phase 4 tears down the test fixture via the _Implicit Teardown_ call,
81+
% |self.tearDown()|. The base class |tearDown()| method does nothing.
82+
%
83+
% Test failure and test error exceptions are caught and handled by the |run()|
84+
% method, so test methods do not need to use try-catch. This facilitates
85+
% simple, straight-line test-method code.
86+
%
87+
% _Note: The |monitor| object will be discussed later._
88+
89+
%% Test Case Discovery
90+
% The static method |TestSuite.fromName| constructs a test suite based on the
91+
% name of an M-file. If the M-file defines a |TestCase| subclass, then |fromName|
92+
% inspects the methods of the class and constructs a |TestCase| object for each
93+
% method whose name begins with "[tT]est". If the M-file does not define a
94+
% |TestCase| subclass, then |fromName| attempts to construct either a simple
95+
% procedural test case or a set of subfunction-based test cases. (See the next
96+
% section).
97+
%
98+
% The static method |TestSuite.fromPwd| constructs a test suite by discovering
99+
% all the test cases in the present working directory. It discovers all
100+
% |TestCase| subclasses in the directory. In addition, it constructs test suites
101+
% from all the procedural M-files in the directory beginning with "[tT]est".
102+
%
103+
% The _File System Test Runner_, |runtests|, provides convenient syntaxes for
104+
% performing test case discovery automatically.
105+
106+
%% FunctionHandleTestCase: For the Procedural World
107+
% Most MATLAB users are much more comfortable with procedural programming. An
108+
% important design goal for MATLAB xUnit is to make it as easy as possible for MATLAB
109+
% users with little object-oriented programming experience to create and run
110+
% their own tests. The FunctionHandleTestCase supplies the plumbing necessary
111+
% to support procedural test functions:
112+
%
113+
% <<class_diagram_b.gif>>
114+
%
115+
% Private properties |SetupFcn|, |TestFcn|, and |TeardownFcn| are procedural
116+
% _function handles_ (similar to function pointers or function references in
117+
% other languages).
118+
%
119+
% |runTestCase()| is the test method used for constructing a TestCase object.
120+
%
121+
% Managing test fixtures requires special consideration, because procedural
122+
% function handles don't have access to object instance data in order to access
123+
% a test fixture.
124+
%
125+
% The overridden |setUp()| method looks at the number of outputs of the function
126+
% handle |SetupFcn|. If it has an output argument, then the argument is saved
127+
% in the private |TestData| property, and |TestData| is then passed to both
128+
% |TestFcn| and |TeardownFcn| for their use.
129+
130+
%% Writing Procedural Test Cases
131+
% Procedural test cases can be written in two ways:
132+
%
133+
% * A simple M-file function that is treated as a single test case
134+
% * An M-file containing multiple subfunctions that are each treated as a test case.
135+
%
136+
% In either case, the test
137+
% case is considered to pass if it executes without error.
138+
%
139+
% Writing one test case per file is not ideal; it would lead to either zillions
140+
% of tiny little test files, or long test methods exhibiting various bad test
141+
% smells (_Multiple Test Conditions_, _Flexible Test_, _Conditional Test Logic_,
142+
% _Eager Test_, _Obscure Test_, etc.) So we need a way to write multiple test
143+
% cases in a single procedural M-file. The natural MATLAB way would be to use
144+
% subfunctions.
145+
%
146+
% However, subfunction-based test cases require special consideration. Consider
147+
% the following M-file structure:
148+
%
149+
% === File A.m ===
150+
% function A
151+
% ...
152+
%
153+
% function B
154+
% ...
155+
%
156+
% function C
157+
% ...
158+
%
159+
% function D
160+
% ...
161+
%
162+
% The first function in the file, |A|, has the same name as the file. When
163+
% other code outside this function calls |A|, it is this first function that
164+
% gets called. Functions |B|, |C|, and |D| are called _subfunctions_.
165+
% Normally, these subfunctions are only visible to and can only be called by
166+
% |A|. The only way that code elsewhere might be able to call |B|, |C|, or |D|
167+
% is if function |A| forms handles to them and passes those handles out of its
168+
% scope. Normally this would be done by returning the function handles as
169+
% output arguments.
170+
%
171+
% Note that no code executing outside the scope of a function in A.m can form
172+
% function handles to |B|, |C|, or |D|, or can even determine that these
173+
% functions exist.
174+
%
175+
% This obviously poses a problem for test discovery!
176+
%
177+
% The MATLAB xUnit solution is to establish the following convention for
178+
% subfunction-based tests. The first function in a test M-file containing
179+
% subfunction tests has to begin with these lines:
180+
%
181+
% === File A.m ===
182+
% function test_suite = A
183+
% initTestSuite;
184+
% ...
185+
%
186+
% |initTestSuite| is a _script_ that runs in the scope of the function |A|.
187+
% |initTestSuite| determines which subfunctions are test functions, as well as setup
188+
% or teardown functions. It forms handles to these functions and constructs a
189+
% set of FunctionHandleTestCase objects, which function |A| returns as the
190+
% output argument |test_suite|.
191+
192+
%% TestRunMonitor
193+
% The abstract |TestRunMonitor| class defines the interface for an object that
194+
% "observe" the in-progress execution of a test suite. MATLAB xUnit provides two
195+
% subclasses of |TestRunMonitor|:
196+
%
197+
% * |TestRunLogger| silently logs test suite events and captures the details of
198+
% any test failures or test errors.
199+
% * |CommandWindowTestRunDisplay| prints the progress of an executing test suite
200+
% to the Command Window.
201+
%
202+
% <<class_diagram_c.gif>>
203+
%
204+
% A TestRunMonitor is passed to the |run()| method of a TestComponent object.
205+
% The |run()| method calls the appropriate notification methods of the
206+
% monitor.
207+
%
208+
% Here is the output when using the CommandWindowTestRunDisplay object on the
209+
% MATLAB xUnit's own test suite:
210+
%
211+
% runtests
212+
% Starting test run with 92 test cases.
213+
% ....................
214+
% ....................
215+
% ....................
216+
% ....................
217+
% ............
218+
% PASSED in 7.040 seconds.
219+
220+
%% File System Test Runner
221+
% MATLAB xUnit provides a command-line _File System Test Runner_ called
222+
% |runtests|. When called with no input arguments, |runtests| gathers all the
223+
% test cases from the current directory and runs them, summarizing the results
224+
% to the Command Window. |runtests| can also take a string argument specifying
225+
% which test file, and optionally which specific test case, to run.
226+
227+
%% Test Selection
228+
% Test selection is supported in |runtests| by passing in a string of the form:
229+
%
230+
% 'Location:Name'
231+
%
232+
% or just:
233+
%
234+
% 'Location'
235+
%
236+
% Both of these forms are handled by |runtests| and by |TestSuite.fromName|.
237+
%
238+
% 'Location' is the name of the M-file containing test cases. 'Name' is the
239+
% name of a specific test case. Normally, the name of the test case is the name
240+
% of the corresponding TestCase method. For FunctionHandleTestCase objects,
241+
% though, 'Name' is the subfunction name.
242+
243+
%% Assertion Methods
244+
% MATLAB xUnit provides the following assertion methods:
245+
%
246+
% * _Stated Outcome Assertion_ (|assertTrue|, |assertFalse|)
247+
% * _Equality Assertion_ (|assertEqual|)
248+
% * _Fuzzy Equality Assertion_ (|assertElementsAlmostEqual|, |assertVectorsAlmostEqual|)
249+
% * _Expected Exception Assertion_ (|assertExceptionRaised|)
250+
%
251+
% Assertion functions are provided via globally accessible names (e.g.,
252+
% |assertEqual|). The assertion functions could be moved to the |xunit|
253+
% package, but MATLAB users are not accustomed yet to packages and package
254+
% name-scoping syntax.
255+
%
256+
% 'message' is the last input to the assertion functions and is optional. (See
257+
% below for discussion of _Assertion Roulette_.)
258+
%
259+
% The _Expected Exception Assertion_, |assertExceptionRaised| is used by forming
260+
% an anonymous function handle from an expression that is expected to error, and
261+
% then passing that function handle to |assertExceptionRaised| along with the
262+
% expected exception identifier. For example:
263+
%
264+
% f = @() sin(1,2,3);
265+
% assertExceptionRaised(f, 'MATLAB:maxrhs')
266+
%
267+
% By using this mechanism, test writers can verify exceptions without using
268+
% try-catch logic in their test code.
269+
270+
%% Stack Traces and "Assertion Roulette"
271+
% _xUnit Test Patterns_ explains the smell _Assertion Roulette_ this way: "It is
272+
% hard to tell which of several assertions within the same test method caused a
273+
% test failure.
274+
%
275+
% MATLAB xUnit mitigates against _Assertion Roulette_ by capturing the entire stack
276+
% trace, including line numbers, for every test failure and test error. (The
277+
% MATLAB MException object, which you obtain via the |catch| clause, contains
278+
% the stack trace.) The stack trace is displayed to the Command Window, with
279+
% clickable links that load the corresponding M-file into editor at the
280+
% appropriate line number.
281+
%
282+
% Stack traces can be pretty long, though. Also, test framework plumbing tends
283+
% to occupy the trace in between the assertion and the user's test code, thus
284+
% making the trace hard to interpret for less-experienced users. MATLAB xUnit,
285+
% therefore, uses a stack filtering heuristic for displaying test fault traces:
286+
% Starting at the deepest call level, once the trace leaves MATLAB xUnit framework
287+
% functions, all further framework functions are filtered out of the stack
288+
% trace.
289+
%
290+
% Here's an example of stack trace display in the output of |runtests|:
291+
%
292+
% <html>
293+
% <tt>
294+
% >> runtests testSample<br />
295+
% Starting test run with 1 test case.<br />
296+
% F<br />
297+
% FAILED in 0.081 seconds.<br />
298+
% <br />
299+
% ===== Test Case Failure =====<br />
300+
% Location: c:\work\matlab_xunit\architecture\testSample.m<br />
301+
% Name: testMyCode<br />
302+
% <br />
303+
% c:\work\matlab_xunit\architecture\testSample.m at <span style="color:blue;
304+
% text-decoration:underline">line 6</span><br />
305+
% <br />
306+
% Input elements are not all equal within relative tolerance: 1.49012e-008<br />
307+
% <br />
308+
% First input:<br />
309+
% 1<br />
310+
% <br />
311+
% Second input:<br />
312+
% 1.1000<br />
313+
% </tt>
314+
% </html>
315+
%
316+
% Clicking on the blue, underlined link above loads the corresponding file into
317+
% the editor, positioned at the appropriate line.
318+
319+
%% Extending the Framework
320+
% The MATLAB xUnit framework can be extended primarily by subclassing |TestCase|,
321+
% |TestSuite|, and |TestMonitor|.
322+
%
323+
% |TestCase| can be subclassed to enable a new set of test cases that all share
324+
% some particular behavior. The MATLAB xUnit Test Framework contains three
325+
% examples of extending |TestCase| behavior in this way:
326+
%
327+
% * |FunctionHandleTestCase| provides the ability to define test cases based on
328+
% procedural function handles.
329+
% * |TestCaseInDir| defines a test case that must be run inside a particular
330+
% directory. The |setUp| and |tearDown| functions are overridden to change the
331+
% MATLAB working directory before running the test case, and then to restore the
332+
% original working directory when the test case finished. The class is used by
333+
% the framework's own test suite.
334+
% * |TestCaseInPath| defines a test case that must be run with a particular
335+
% directory temporarily added to the MATLAB path. Its implementation is similar
336+
% to |TestCaseInDir|, and it is also used by the framework's own test suite.
337+
%
338+
% |TestSuite| could be similarly extended by subclassing. This might a provide a
339+
% way in the future to define a test suite containing collections of test
340+
% components in separate directories, which is not currently supported.
341+
%
342+
% Finally |TestRunMonitor| could be subclassed to support a variety of test
343+
% monitoring mechanisms, such as what might be required by a _Graphical Test
344+
% Runner_.

architecture/testSample.m

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function test_suite = testSample
2+
initTestSuite;
3+
4+
function testMyCode
5+
assertEqual(1, 1);
6+
assertElementsAlmostEqual(1, 1.1);
7+
assertTrue(10 == 10);

doc/+abc/+tests/test_that.m

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
% Do-nothing test used in the examples for organizing tests inside packages.
2+
%
3+
% Steven L. Eddins
4+
% Copyright 2010 The MathWorks, Inc.
5+
6+
function test_that

doc/+abc/+tests/test_this.m

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
% Do-nothing test used in the examples for organizing tests inside packages.
2+
%
3+
% Steven L. Eddins
4+
% Copyright 2010 The MathWorks, Inc.
5+
6+
function test_this

doc/+abc_tests/test_that.m

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
% Do-nothing test used in the examples for organizing tests inside packages.
2+
%
3+
% Steven L. Eddins
4+
% Copyright 2010 The MathWorks, Inc.
5+
6+
function test_that

doc/+abc_tests/test_this.m

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
% Do-nothing test used in the examples for organizing tests inside packages.
2+
%
3+
% Steven L. Eddins
4+
% Copyright 2010 The MathWorks, Inc.
5+
6+
function test_this

0 commit comments

Comments
 (0)