Can I set unit test TestParameter properties using functions not on the path?

7 vues (au cours des 30 derniers jours)
I would like to write a unit test for a method on an ENUM class, using all possible enumerations of that ENUM class as a TestParameter. The ENUM class, as well as its corresponding unit test, is part of a repository, so I'd like to be diligent when setting up the paths to ensure that neither the unit test nor the ENUM itself is dependent on any code I have locally on my machine (and similar for any developers). Therefore I'd like to utilize PathFixtures to handle adding and removing from the Matlab path. I can't figure out how to set the TestParameter properties given this setup, since the TestParameter block requires the ENUM class to be on the path.
The ENUM classdef m-file (MyClass.m) looks like this:
classdef MyClass
A( 1, 2 )
B( 3, 4 )
function this = MyClass( input1, input2 )
this.prop1 = input1;
this.prop2 = input2;
function output = SomeMethod( this )
output = this.prop1 + this.prop2;
The unit test code (MyClassTest.m) looks like this:
classdef MyClassTest < matlab.unittest.TestCase
properties( TestParameter )
allPossibleEnums = arrayfun( @( x ) x, ...
eval( 'enumeration( ''MyClass'' )' ), ...
'UniformOutput', false );
methods( TestClassSetup = true )
function SetUpPaths( testCase )
testCase.applyFixture( matlab.unittest.fixtures.PathFixture( ...
PathToMyClass ) );
methods( Test = true, ParameterCombination = 'sequential' )
function SomeMethodTest( testCase, allPossibleEnums )
output = allPossibleEnums.SomeMethod();
check = allPossibleEnums.prop1 + allPossibleEnums.prop2;
testCase.verifyEqual( output, check );
My issue is that the properties block to define allPossibleEnums requires PathToMyClass be on the Matlab path prior to running the constructor for MyClassTest. I tried using a SharedTestFixtures for MyClassTest but that appears to require a hard-coded path, and I'd like other developers to be able to run the unit test without having to modify it when they check it out. I could also write a script and add the path to MyClass with an addpath( ... ) call prior to constructing the MyClassTest, but that loses the robustness I'd like when using a PathFixtures. I could also hard-code allPossibleEnums as a cell array of strings containing all the possible enumerations, but that would need to be updated by hand should the enumeration list change. And I could simply leave the TestParameter properties empty and just create the enumeration list within the SomeMethodTest method and write a "for" loop, but that would seem to defeat the purpose of having a "sequential" parameter option and wouldn't allow me to see which enumeration caused a failure (I would also have to repeat the creation of the enumeration list in any additional test methods).
Is there any way around this? Am I simply misunderstanding how to use the unit test framework or the PathFixtures? Is there a different/better way to list out all the possible enumerations of MyClass as a TestParameter?

Réponse acceptée

Andy Campbell
Andy Campbell le 18 Jan 2017
Modifié(e) : Andy Campbell le 18 Jan 2017
Hey Matt,
The problem at play here is the fact that your test class definition itself (what happens the first time you load the class) is itself dependent on something that is not available. You are trying to make it available via the PathFixture, but that only gets applied at test run time, not test class loading time.
Have you considered deploying the source to in toolbox form? Doing so would allow you to perhaps install toolboxes at test runtime and all the path management would be handled by the toolbox packaging features. (see here and here for example).
If that does't work out, then you'll need to do something like the following:
SharedTestFixtures ={matlab.unittest.fixtures.PathFixture(fullfile(pwd,'source'))})...
MyClassTest < matlab.unittest.TestCase
properties( TestParameter )
enumName = getEnumNames
methods(Test, ParameterCombination = 'sequential' )
function SomeMethodTest( testCase, enumName )
thisEnum = MyClass.(enumName);
output = thisEnum.SomeMethod();
check = thisEnum.prop1 + thisEnum.prop2;
testCase.verifyEqual( output, check );
function names = getEnumNames
oldPath = path;
cl = onCleanup(@() path(oldPath));
names = cellstr(enumeration('MyClass'));
This ensures that the source code is on the path both at class load time (when the TestParameters are getting populated) and at test runtime (via the SharedTestFixture).
Hope that helps!
  2 commentaires
Matt le 21 Jan 2017
Thanks for the help, Andy! I'm intrigued by the toolbox builder, but for the moment I'm going to see if your workaround use of a local function will help - the code I wrote about is part of a larger codebase that will require some coordination in order to package up properly. Thanks again!
Andy Campbell
Andy Campbell le 24 Avr 2019
Note, now in 19a you can use a MATLAB project which will handle the path setup for you before laoding the test classes. More info here:

Connectez-vous pour commenter.

Plus de réponses (0)


En savoir plus sur Function-Based Unit Tests dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by