├── tbx
├── doc
│ ├── GettingStarted.mlx
│ └── GettingStarted.pdf
├── robust2018
│ ├── findArea.mlx
│ ├── PropertyValidation.mlx
│ ├── CreateMockObjectExample.mlx
│ ├── DataService.m
│ ├── myUnsafeFileWriter.m
│ ├── ValidateProps.m
│ ├── trader.m
│ ├── mySafeFileTxtWriter.m
│ ├── functionSignatures.json
│ ├── Contents.m
│ ├── BankAccount.m
│ └── html
│ │ ├── helptoc.xml
│ │ ├── PropertyValidation.html
│ │ └── CreateMockObjectExample.html
├── apps
│ ├── ConfigurePlot.mlappinstall
│ ├── ConfigurePlotAppExample.mlapp
│ └── ConfigurePlotAppScreenshot.png
├── info.xml
└── demos.xml
├── finance-conference-signature.png
├── README.md
├── runTestsWithCobeturaCodeCoverage.m
├── test
├── tBankAccount.m
├── testConfigurePlotAppExample.m
├── testFindArea.m
└── TraderTest.m
├── LICENSE
├── ConfigurePlot.prj
└── robust2018.prj
/tbx/doc/GettingStarted.mlx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/doc/GettingStarted.mlx
--------------------------------------------------------------------------------
/tbx/doc/GettingStarted.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/doc/GettingStarted.pdf
--------------------------------------------------------------------------------
/tbx/robust2018/findArea.mlx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/robust2018/findArea.mlx
--------------------------------------------------------------------------------
/finance-conference-signature.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/finance-conference-signature.png
--------------------------------------------------------------------------------
/tbx/apps/ConfigurePlot.mlappinstall:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/apps/ConfigurePlot.mlappinstall
--------------------------------------------------------------------------------
/tbx/robust2018/PropertyValidation.mlx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/robust2018/PropertyValidation.mlx
--------------------------------------------------------------------------------
/tbx/apps/ConfigurePlotAppExample.mlapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/apps/ConfigurePlotAppExample.mlapp
--------------------------------------------------------------------------------
/tbx/apps/ConfigurePlotAppScreenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/apps/ConfigurePlotAppScreenshot.png
--------------------------------------------------------------------------------
/tbx/robust2018/CreateMockObjectExample.mlx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/robust-matlab-2018/HEAD/tbx/robust2018/CreateMockObjectExample.mlx
--------------------------------------------------------------------------------
/tbx/robust2018/DataService.m:
--------------------------------------------------------------------------------
1 | classdef DataService
2 | % a data service to retrieve the stock price data
3 |
4 | % Copyright 2018 MathWorks Inc.
5 | methods (Abstract,Static)
6 | price = lookupPrice(ticker,date)
7 | end
8 | end
--------------------------------------------------------------------------------
/tbx/robust2018/myUnsafeFileWriter.m:
--------------------------------------------------------------------------------
1 | function myUnsafeFileWriter( filename, data )
2 | % myUnsafeFileWriter writes data to a file without cleaning up
3 |
4 | % Copyright 2018 MathWorks Inc.
5 |
6 | fid = fopen( filename, 'w' );
7 | fprintf( fid, '%s\n', data );
8 | fclose( fid );
9 |
10 | end
11 |
--------------------------------------------------------------------------------
/tbx/robust2018/ValidateProps.m:
--------------------------------------------------------------------------------
1 | classdef ValidateProps
2 | % The ValidateProps class defines three properties with validation
3 |
4 | % Copyright 2018 MathWorks Inc.
5 | properties
6 | Location(1,3) double {mustBeReal, mustBeFinite}
7 | Label(1,:) char {mustBeMember(Label,{'High','Medium','Low'})} = 'Low'
8 | State(1,1) matlab.lang.OnOffSwitchState
9 | end
10 | end
--------------------------------------------------------------------------------
/tbx/robust2018/trader.m:
--------------------------------------------------------------------------------
1 | function trader(dataService,broker,ticker,numShares)
2 | % an algorithm for buying stock
3 |
4 | % Copyright 2018 MathWorks Inc.
5 |
6 | yesterday = datetime('yesterday');
7 | priceYesterday = dataService.lookupPrice(ticker,yesterday);
8 | price2DaysAgo = dataService.lookupPrice(ticker,yesterday-days(1));
9 |
10 | if priceYesterday < price2DaysAgo
11 | broker.buy(ticker,numShares);
12 | end
13 | end
--------------------------------------------------------------------------------
/tbx/robust2018/mySafeFileTxtWriter.m:
--------------------------------------------------------------------------------
1 | function mySafeFileTxtWriter( filename, data )
2 | % mySafeFileTxtWriter writes data to a text file and cleans up
3 |
4 | % Copyright 2018 MathWorks Inc.
5 |
6 | [~,~,ext] = fileparts( filename );
7 | if ~strcmpi( ext, '.txt' )
8 | error( 'mySafeFileTxtWriter:InvalidFileExtension', ...
9 | 'Filename input must have a ''.txt'' extension. Extension supplied was ''%s''', ...
10 | ext );
11 |
12 | end
13 |
14 | fid = fopen( filename, 'w' );
15 | c = onCleanup( @() fclose(fid) );
16 |
17 | fprintf( '%s\n', data );
18 |
19 | end
20 |
--------------------------------------------------------------------------------
/tbx/robust2018/functionSignatures.json:
--------------------------------------------------------------------------------
1 | {
2 | "_schemaVersion": "1.0.0",
3 | "findArea": {
4 | "inputs": [
5 | {
6 | "name": "shape",
7 | "kind": "required",
8 | "type": [
9 | "char",
10 | "choices={'circle','rectangle'}"
11 | ],
12 | "purpose": "shape"
13 | },
14 | {
15 | "name": "dim1",
16 | "kind": "required",
17 | "type": [
18 | "numeric"
19 | ],
20 | "purpose": "1st dimension"
21 | },
22 | {
23 | "name": "dim2",
24 | "kind": "ordered",
25 | "type": [
26 | "numeric"
27 | ],
28 | "purpose": "2nd dimension"
29 | }
30 | ]
31 | }
32 | }
--------------------------------------------------------------------------------
/tbx/robust2018/Contents.m:
--------------------------------------------------------------------------------
1 | % ROBUST2018
2 | % Version 1.0 24-May-2018
3 | %
4 | % Files
5 | % DataService - a data service to retrieve the stock price data
6 | % mySafeFileTxtWriter - mySafeFileTxtWriter writes data to a text file and cleans up
7 | % myUnsafeFileWriter - myUnsafeFileWriter writes data to a file without cleaning up
8 | % trader - an algorithm for buying stock
9 | % ValidateProps - The ValidateProps class defines three properties with validation
10 | % findArea - returns the area of shape with given dimensions
11 | % CreateMockObjectExample - test an algorithm for buying stock, but do not test the entire system
12 | % PropertyValidation - example showing validation on property values
13 | %
14 | % Copyright 2018 MathWorks Inc.
15 |
--------------------------------------------------------------------------------
/tbx/robust2018/BankAccount.m:
--------------------------------------------------------------------------------
1 | classdef BankAccount
2 |
3 | properties
4 | AccountNumber
5 | AccountBalance
6 | AccountStatus
7 | end
8 |
9 | methods
10 |
11 | function ba = BankAccount(accountNumber, accountBalance)
12 | ba.AccountNumber = accountNumber;
13 | ba.AccountBalance = accountBalance;
14 | ba.AccountStatus = 'Open';
15 | end
16 |
17 | function ba = deposit(ba, amount)
18 | validateattributes(amount, {'double'}, {'scalar', 'positive'});
19 | ba.AccountBalance = ba.AccountBalance + amount;
20 | end
21 |
22 | function ba = withdraw(ba, amount)
23 | ba.AccountBalance = ba.AccountBalance - amount;
24 | if ba.AccountBalance < 0
25 | ba.AccountStatus = 'Overdraft';
26 | end
27 | end
28 |
29 | end
30 | end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Developing Robust MATLAB Code
2 | Paul Peeling, Mathworks
3 |
4 | As the size and complexity of your MATLAB® application increases, you want make sure to structure software projects well, ensuring users can run code without encountering unexpected behaviour or errors, for example. In this talk, you will learn about relevant advanced MATLAB software development capabilities, including error handling, object-oriented programming (OOP), unit testing, version control, and change tracking.
5 |
6 | This repository provides the code and examples used in the session.
7 |
8 | Code coverage report for this repository can be generated by the [codecov.io](https://codecov.io) service as described in a recent Developer Zone blog post: [Cov’ed Code All Throughout the Interwebs](https://blogs.mathworks.com/developer/2018/04/17/codecov-and-cobertura/)
9 |
10 | To generate code coverage, run the script
11 | ```
12 | runTestsWithCobeturaCodeCoverage.m
13 | ```
14 |
--------------------------------------------------------------------------------
/runTestsWithCobeturaCodeCoverage.m:
--------------------------------------------------------------------------------
1 | %% Run tests and collect coverage information
2 |
3 | import matlab.unittest.TestRunner
4 | import matlab.unittest.TestSuite
5 | import matlab.unittest.plugins.CodeCoveragePlugin
6 | import matlab.unittest.plugins.codecoverage.CoberturaFormat
7 |
8 | % Define test suite
9 | suite = TestSuite.fromFolder( 'test' );
10 |
11 | % Create and configure the runner
12 | runner = TestRunner.withTextOutput('Verbosity',3);
13 | src = fullfile(pwd,'tbx','robust2018');
14 | coverageFile = fullfile(pwd, 'coverage.xml');
15 | runner.addPlugin(CodeCoveragePlugin.forFolder(src,...
16 | 'Producing', CoberturaFormat(coverageFile)));
17 |
18 | results = runner.run(suite)
19 |
20 | %%
21 | token = '8d46bba7-22e7-4ce1-9dc5-02a052fd6b8e';
22 | setenv( 'CODECOV_TOKEN', token );
23 |
24 | !C:\PROGRA~1\Git\mingw64\bin\curl.exe -s https://codecov.io/bash | C:\PROGRA~1\Git\bin\bash.exe -s || - echo "Codecov did not collect coverage reports"
25 | web( 'https://codecov.io/gh/mathworks/robust-matlab-2018/' )
--------------------------------------------------------------------------------
/test/tBankAccount.m:
--------------------------------------------------------------------------------
1 | classdef tBankAccount < matlab.unittest.TestCase
2 | % Tests the BankAccount class.
3 |
4 | % Copyright 2018 MathWorks Inc.
5 |
6 | methods (Test)
7 |
8 | function testCreation(testCase)
9 | ba = BankAccount(1234, 100);
10 | testCase.verifyEqual(ba.AccountNumber, 1234, ...
11 | 'Constructor failed to correctly set account number');
12 | testCase.verifyEqual(ba.AccountBalance, 100, ...
13 | 'Constructor failed to correctly set account balance');
14 | end
15 |
16 | function testDesposit(testCase)
17 | ba = BankAccount(1234, 100);
18 | ba = ba.deposit(25);
19 | testCase.verifyEqual(ba.AccountBalance, 125);
20 | end
21 |
22 | function testWithdraw(testCase)
23 | ba = BankAccount(1234, 100);
24 | ba = ba.withdraw(25);
25 | testCase.verifyEqual(ba.AccountBalance, 75);
26 | end
27 |
28 | end
29 | end
--------------------------------------------------------------------------------
/tbx/info.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2018a
4 | robust2018
5 | toolbox
6 |
7 | robust2018\html
8 |
9 |
--------------------------------------------------------------------------------
/test/testConfigurePlotAppExample.m:
--------------------------------------------------------------------------------
1 | classdef testConfigurePlotAppExample < matlab.uitest.TestCase
2 |
3 | % Copyright 2018 MathWorks Inc.
4 |
5 | methods (Test)
6 | function test_SampleSize(testCase)
7 | app = ConfigurePlotAppExample;
8 | testCase.addTeardown(@delete,app);
9 |
10 | testCase.type(app.SampleSizeEditField,12);
11 | testCase.press(app.UpdatePlotButton);
12 |
13 | ax = app.UIAxes;
14 | surfaceObj = ax.Children;
15 | testCase.verifySize(surfaceObj.ZData,[12 12]);
16 | end
17 |
18 | function test_Colormap(testCase)
19 | app = ConfigurePlotAppExample;
20 | testCase.addTeardown(@delete,app);
21 |
22 | testCase.choose(app.ColormapDropDown,'Winter');
23 | testCase.press(app.UpdatePlotButton);
24 |
25 | expectedMap = winter;
26 | ax = app.UIAxes;
27 | testCase.verifyEqual(ax.Colormap,expectedMap);
28 | end
29 | end
30 |
31 | end
--------------------------------------------------------------------------------
/tbx/demos.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | robust2018
4 | toolbox
5 | HelpIcon.DEMOS
6 |
7 | Code and examples accompanying the session "Developing Robust MATLAB Code" at the MATLAB Computational Finance Conference 2018
8 |
9 | robust2018
10 |
11 | CreateMockObjectExample
12 | other
13 | CreateMockObjectExample
14 | robust2018/html/CreateMockObjectExample.html
15 |
16 |
17 | PropertyValidation
18 | other
19 | PropertyValidation
20 | robust2018/html/PropertyValidation.html
21 |
22 |
23 | findArea
24 | other
25 | findArea
26 | robust2018/html/findArea.html
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018, The MathWorks, Inc.
2 | All rights reserved.
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
5 | 2. 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.
6 | 3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings.
7 | 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 HOLDER 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.
8 |
--------------------------------------------------------------------------------
/test/testFindArea.m:
--------------------------------------------------------------------------------
1 | classdef testFindArea < matlab.unittest.TestCase
2 | % testFindArea unit tests for findArea
3 |
4 | % Copyright 2018 MathWorks Inc.
5 |
6 | properties
7 | Circle
8 | Rectangle
9 | Figure
10 | Axes
11 | end
12 |
13 | methods ( TestClassSetup )
14 |
15 | function drawShapesOnAxes( test )
16 |
17 | test.Figure = figure;
18 | test.Axes = axes( 'Parent', test.Figure );
19 | test.Rectangle = rectangle( test.Axes, 'Position', [-1 -1 1 1] );
20 | test.Circle = rectangle( test.Axes, 'Position', [-1 -1 2 2], 'Curvature', 1 );
21 |
22 | end
23 |
24 | end
25 |
26 | methods ( Test )
27 |
28 | function circleIsRound( test )
29 |
30 | expectedArea = (test.Axes.YLim(2) - test.Axes.YLim(1))^2 * pi;
31 | actualArea = findArea( 'circle', test.Circle.Position(3) );
32 |
33 | test.verifyEqual( actualArea, expectedArea, 'AbsTol', 0.01 );
34 |
35 | end
36 |
37 | function rectangleIsSquare( test )
38 |
39 | expectedArea = test.Rectangle.Position(3)^2;
40 | % Second dimension is treated as 1
41 | actualArea = findArea( 'rectangle', test.Rectangle.Position(3) );
42 |
43 | test.verifyEqual( actualArea, expectedArea, 'AbsTol', 0.01 );
44 |
45 | end
46 |
47 | function shapeIsKnown( test )
48 |
49 | test.verifyError( @() findArea( 'circle' ), 'MATLAB:narginchk:notEnoughInputs' );
50 | test.verifyError( @() findArea( 'box', 3, 4 ), 'MATLAB:findArea:unrecognizedStringChoice' );
51 |
52 | end
53 |
54 | end
55 |
56 | methods ( TestClassTeardown )
57 |
58 | function closeFigure( test )
59 |
60 | close( test.Figure )
61 |
62 | end
63 |
64 | end
65 |
66 | end
67 |
--------------------------------------------------------------------------------
/test/TraderTest.m:
--------------------------------------------------------------------------------
1 | classdef TraderTest < matlab.mock.TestCase
2 |
3 | % Copyright 2018 MathWorks Inc.
4 |
5 | methods(Test)
6 | function buysStockWhenDrops(testCase)
7 | import matlab.unittest.constraints.IsLessThan
8 | import matlab.unittest.constraints.IsAnything
9 | import matlab.mock.constraints.WasCalled
10 | yesterday = datetime('yesterday');
11 |
12 | % Create mocks
13 | [stubDataService,dataServiceBehavior] = createMock(testCase, ...
14 | ?DataService);
15 | [spyBroker,brokerBehavior] = createMock(testCase, ...
16 | 'AddedMethods',{'buy'});
17 |
18 | % Set up behavior
19 | testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice(...
20 | "FOO",yesterday),123);
21 | testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice(...
22 | "FOO",IsLessThan(yesterday)),234);
23 |
24 | % Call function under test
25 | trader(stubDataService,spyBroker,"FOO",100)
26 | trader(stubDataService,spyBroker,"FOO",75)
27 |
28 | % Verify interactions
29 | testCase.verifyCalled(brokerBehavior.buy("FOO",100))
30 | testCase.verifyThat(brokerBehavior.buy("FOO",IsAnything), ...
31 | WasCalled('WithCount',2))
32 | end
33 | function doesNotBuyStockWhenIncreases(testCase)
34 | import matlab.unittest.constraints.IsLessThan
35 | yesterday = datetime('yesterday');
36 |
37 | % Create mocks
38 | [stubDataService,dataServiceBehavior] = createMock(testCase, ...
39 | ?DataService);
40 | [spyBroker,brokerBehavior] = createMock(testCase, ...
41 | 'AddedMethods',{'buy'});
42 |
43 | % Set up behavior
44 | testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice(...
45 | "BAR",yesterday),765);
46 | testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice(...
47 | "BAR",IsLessThan(yesterday)),543);
48 |
49 | % Call function under test
50 | trader(stubDataService,spyBroker,"BAR",100)
51 |
52 | % Verify interactions
53 | testCase.verifyNotCalled(brokerBehavior.buy("BAR",100))
54 | end
55 | end
56 | end
--------------------------------------------------------------------------------
/ConfigurePlot.prj:
--------------------------------------------------------------------------------
1 |
2 |
3 | ConfigurePlot
4 | Paul Peeling
5 | paul.peeling@mathworks.co.uk
6 | MathWorks
7 |
8 |
9 | Configure a MATLAB Plot
10 |
11 | ${PROJECT_ROOT}\tbx\apps\ConfigurePlotAppScreenshot.png
12 | 1.0
13 |
14 | - MATLAB
15 |
16 |
17 | - 1
18 |
19 |
20 | - 9.4
21 |
22 |
23 | ${PROJECT_ROOT}\tbx\apps
24 | a4d5955f-6c8c-4f2f-8ff4-8c8a04d6a597
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ${PROJECT_ROOT}\tbx\apps\ConfigurePlotAppExample.mlapp
37 |
38 |
39 |
40 |
41 |
42 | C:\Users\ppeeling\git\fin-conf-2018\tbx\apps
43 |
44 |
45 |
46 | C:\Program Files\MATLAB\R2018a
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | true
58 |
59 |
60 |
61 |
62 | true
63 |
64 |
65 |
66 |
67 | true
68 |
69 |
70 |
71 |
72 | true
73 |
74 |
75 |
76 |
77 | true
78 |
79 |
80 |
81 |
82 | true
83 |
84 |
85 |
86 |
87 | false
88 | false
89 | true
90 | false
91 | false
92 | false
93 | false
94 | false
95 | 10.0
96 | false
97 | true
98 | win64
99 | true
100 |
101 |
102 |
--------------------------------------------------------------------------------
/tbx/robust2018/html/helptoc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MyToolbox Toolbox
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Getting Started with the MyToolbox Toolbox
19 | System Requirements
20 |
21 | Features
22 |
23 | Feature 1
24 |
25 | Feature 2
26 |
27 |
28 |
29 |
30 | MyToolbox User Guide
32 | Setting Up MyToolbox
33 |
34 | Processing Data
35 |
36 | Verifying MyToolbox outputs
37 | Handling Test Failures
38 |
39 |
40 |
41 |
42 |
43 | Function Reference
45 |
46 | First Category
47 |
48 | function_1
49 | function_2
50 |
51 |
52 |
53 | Second Category
54 |
55 | function_3
56 | function_4
57 |
58 |
59 |
60 | Third category
61 |
62 |
63 |
64 |
65 | Mytoolbox Examples
67 |
68 |
69 |
71 | MyToolbox Web Site (Example only: goes to mathworks.com)
72 |
73 |
74 |
--------------------------------------------------------------------------------
/robust2018.prj:
--------------------------------------------------------------------------------
1 |
2 |
3 | robust2018
4 | Paul Peeling
5 | ppeeling@mathworks.com
6 | MathWorks Inc.
7 | Code and Examples from "Developing Robust MATLAB Code"
8 | Code and examples accompanying the session "Developing Robust MATLAB Code" at the MATLAB Computational Finance Conference 2018
9 | ${PROJECT_ROOT}\finance-conference-signature.png
10 | 1.1
11 | ${PROJECT_ROOT}\robust2018.mltbx
12 |
13 | - MATLAB
14 |
15 |
16 | - 1
17 |
18 |
19 | - 9.6
20 |
21 |
22 | 0b8e6fb3-8c8e-4d92-b4a0-27e66c584354
23 |
24 | true
25 | <?xml version="1.0" encoding="utf-8"?>
26 | <examples>
27 | <exampleCategory name="robust2018">
28 | <example name="CreateMockObjectExample" type="html">
29 | <file type="source">/robust2018/html/CreateMockObjectExample.html</file>
30 | <file type="main">/robust2018/CreateMockObjectExample.mlx</file>
31 | <file type="thumbnail"/>
32 | </example>
33 | <example name="PropertyValidation" type="html">
34 | <file type="source">/robust2018/html/PropertyValidation.html</file>
35 | <file type="main">/robust2018/PropertyValidation.mlx</file>
36 | <file type="thumbnail"/>
37 | </example>
38 | <example name="findArea" type="html">
39 | <file type="source">/robust2018/html/findArea.html</file>
40 | <file type="main">/robust2018/findArea.mlx</file>
41 | <file type="thumbnail"/>
42 | </example>
43 | </exampleCategory>
44 | </examples>
45 |
46 |
47 | ${PROJECT_ROOT}\tbx\apps\ConfigurePlot.mlappinstall
48 |
49 |
50 | ${PROJECT_ROOT}\tbx\info.xml
51 | ${PROJECT_ROOT}\tbx\doc\GettingStarted.mlx
52 |
53 |
54 | true
55 |
56 |
57 |
58 | R2018a
59 | latest
60 | false
61 | true
62 | true
63 | true
64 | true
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | ${PROJECT_ROOT}\tbx
100 |
101 |
102 | ${PROJECT_ROOT}\tbx\apps
103 | ${PROJECT_ROOT}\tbx\demos.xml
104 | ${PROJECT_ROOT}\tbx\doc
105 | ${PROJECT_ROOT}\tbx\info.xml
106 | ${PROJECT_ROOT}\tbx\robust2018
107 |
108 |
109 |
110 |
111 |
112 | C:\Users\ppeeling\robust-matlab-2018\robust2018.mltbx
113 |
114 |
115 |
116 | C:\Program Files\MATLAB\R2019a
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | true
128 |
129 |
130 |
131 |
132 | true
133 |
134 |
135 |
136 |
137 | true
138 |
139 |
140 |
141 |
142 | true
143 |
144 |
145 |
146 |
147 | true
148 |
149 |
150 |
151 |
152 | true
153 |
154 |
155 |
156 |
157 | false
158 | false
159 | true
160 | false
161 | false
162 | false
163 | false
164 | false
165 | 10.0
166 | false
167 | true
168 | win64
169 | true
170 |
171 |
172 |
--------------------------------------------------------------------------------
/tbx/robust2018/html/PropertyValidation.html:
--------------------------------------------------------------------------------
1 |
2 |
Sample Class Using Property Validation Sample Class Using Property Validation The ValidateProps class defines three properties with validation.
type ValidateProps.m
classdef ValidateProps
31 |
32 | % Copyright 2018 MathWorks
33 | properties
34 | Location(1,3) double {mustBeReal, mustBeFinite}
35 | Label(1,:) char {mustBeMember(Label,{'High','Medium','Low'})} = 'Low'
36 | State(1,1) matlab.lang.OnOffSwitchState
37 | end
38 | end
Location must be a 1-by-3 array of class double whose values are real, finite numbers. Label must be a char vector that is either 'High' , 'Medium' , or 'Low' . State must be an enumeration member of the matlab.lang.OnOffSwitchState class ( off or on ). Validation at Instantiation Creating an object of the ValidateProps class performs the validation on implicit and explicit default values:
a = ValidateProps
a =
ValidateProps with properties:
39 |
40 | Location: [0 0 0]
41 | Label: 'Low'
42 | State: off
43 |
When creating the object, MATLAB:
Initializes the Location property value to [0 0 0] to satisfy the size and class requirements. Sets the Label property to its default value, 'Low' . The default value must be a member of the allowed set of values. The empty char implicit default value would cause an error. Sets the State property to the off enumeration member defined by the matlab.lang.OnOffSwitchState class. Property Validation and Errors a.Label = 'High'
a =
ValidateProps with properties:
44 |
45 | Location: [0 0 0]
46 | Label: 'High'
47 | State: off
48 |
The State property accepts values of 'on' and 'off' and logical true , false , 1 , or 0 .
a.State = true
a =
ValidateProps with properties:
49 |
50 | Location: [0 0 0]
51 | Label: 'High'
52 | State: on
53 |
Property Validation Errors a.Location = [54 55]
Error setting property 'Location' of class 'ValidateProps': Size of value must match specified dimensions 1×3 or be scalar.
Copyright 2018 MathWorks Inc
54 |
55 |
--------------------------------------------------------------------------------
/tbx/robust2018/html/CreateMockObjectExample.html:
--------------------------------------------------------------------------------
1 |
2 | Mocking Framework Mocking Framework Create mocks for the depended-on components. Define behaviors of the mocks. Test the component of interest. Qualify interactions between the component of interest and the mocked components. Stubbing - define behaviour Spying - intercept and remember Create a mock test case for interactive use.
import matlab.mock.TestCase
testCase = TestCase.forInteractiveUse
testCase =
InteractiveTestCase with no properties.
36 |
Depended on Components The day-trading algorithm has two dependencies: a data service to retrieve the stock price data and a broker to purchase the stock.
type DataService.m
classdef DataService
37 | % a data service to retrieve the stock price data
38 |
39 | % Copyright 2018 MathWorks Inc.
40 | methods (Abstract,Static)
41 | price = lookupPrice(ticker,date)
42 | end
43 | end
In production code, there could be several concrete implementations of the DataService class, such as a BloombergDataService class.
Create Stub to Define Behavior Create a mock for the data service dependency. The data service mock returns predefined values.
[stubDataService,dataServiceBehavior] = createMock(testCase,?DataService);
methods(stubDataService)
Methods for class matlab.mock.classes.DataServiceMock:
44 |
45 |
46 |
47 | Static methods:
48 |
49 | lookupPrice
In the DataService class, the lookupPrice method is abstract and static. The mocking framework implements this method as concrete and static.
Define behavior for the data service mock.
import matlab.unittest.constraints.IsLessThan
yesterday = datetime( 'yesterday' );
testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice( ...
testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice( ...
"FOO" ,IsLessThan(yesterday)),234);
testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice( ...
testCase.assignOutputsWhen(dataServiceBehavior.lookupPrice( ...
"BAR" ,IsLessThan(yesterday)),543);
You can now call the mocked lookupPrice method.
p1 = stubDataService.lookupPrice( "FOO" ,yesterday)
p2 = stubDataService.lookupPrice( "BAR" ,yesterday-days(5))
Create Spy to Intercept Messages Create a mock for the broker dependency.
[spyBroker,brokerBehavior] = createMock(testCase, 'AddedMethods' ,{ 'buy' });
methods(spyBroker)
Methods for class matlab.mock.classes.Mock_1:
50 |
51 | buy
s2 = spyBroker.buy( "inputs" ,[13 42])
Call Component Under Test Call the trader function. Pass in the spyBroker and stubDataService mocks.
trader(stubDataService,spyBroker, "FOO" ,100)
trader(stubDataService,spyBroker, "FOO" ,75)
trader(stubDataService,spyBroker, "BAR" ,100)
Verify Function Interactions Use the broker behavior object (the spy) to verify that the trader function calls the buy method, as expected.
Use the TestCase.verifyCalled method to verify that the trader function instructed the buy method to buy 100 shares of the FOO stock.
import matlab.mock.constraints.WasCalled ;
testCase.verifyCalled(brokerBehavior.buy( "FOO" ,100))
Interactive verification passed.
Verify that FOO stock was purchased two times, regardless of the specified number of shares. While the verifyCalled method is convenient to specify behavior, there is more functionality if you use the WasCalled constraint. For example, you can verify that a mocked method was called a specified number of times.
import matlab.unittest.constraints.IsAnything
testCase.verifyThat(brokerBehavior.buy( "FOO" ,IsAnything), ...
WasCalled( 'WithCount' ,2))
Interactive verification passed.
Verify that the buy method was not called requesting 100 shares of the BAR stock.
testCase.verifyNotCalled(brokerBehavior.buy( "BAR" ,100))
Interactive verification passed.
Although the trader function was called requesting 100 shares of BAR stock, the stub defined yesterday's price for BAR to return a higher value than all days prior to yesterday. Therefore, the broker never buys stock "BAR" .
Copyright 2018 MathWorks Inc.
54 |
55 |
--------------------------------------------------------------------------------