From 572463c7e71c3fc363cb7b155489fd84c483bd10 Mon Sep 17 00:00:00 2001 From: Miles Wells Date: Mon, 27 Jan 2020 22:30:06 +0200 Subject: [PATCH 1/2] Fix for eui.ExpPanel/live input parse error and tests added --- +eui/ExpPanel.m | 22 ++++---- tests/ExpPanelTest.m | 124 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 127 insertions(+), 19 deletions(-) diff --git a/+eui/ExpPanel.m b/+eui/ExpPanel.m index fb1cc885..40dc9086 100644 --- a/+eui/ExpPanel.m +++ b/+eui/ExpPanel.m @@ -108,19 +108,19 @@ % Outputs: % p (eui.ExpPanel) : handle to the panel object. % - p = inputParser; - addRequired(p, 'parent'); - addRequired(p, 'ref'); - addRequired(p, 'remoteRig'); - addRequired(p, 'paramsStruct'); + in = inputParser; + addRequired(in, 'parent'); + addRequired(in, 'ref'); + addRequired(in, 'remoteRig'); + addRequired(in, 'paramsStruct'); % Activate log - addParameter(p, 'activateLog', true); + addOptional(in, 'activateLog', true); % Resume experiment listening (experiment had alread started) - addParameter(p, 'startedTime', []); - parse(p, pos, t, Fs, varargin{:}); + addOptional(in, 'startedTime', []); + in.parse(parent, ref, remoteRig, paramsStruct, varargin{:}) - p = p.Results; % Final parameters - if p.activateLog + in = in.Results; % Final parameters + if in.activateLog subject = dat.parseExpRef(ref); % Extract subject, date and seq from experiment ref try logEntry = dat.addLogEntry(... % Add new entry to log @@ -162,7 +162,7 @@ @() set(p.StopButtons, 'Enable', 'off'))); p.Root.Title = sprintf('%s on ''%s''', p.Ref, remoteRig.Name); % Set experiment panel title - if ~isempty(p.startedTime) + if ~isempty(in.startedTime) % If the experiment has all ready started, trigger all dependent % events. p.expStarted(remoteRig, srv.ExpEvent('started', ref, p.startedTime)); diff --git a/tests/ExpPanelTest.m b/tests/ExpPanelTest.m index a3bcb844..a73b68ac 100644 --- a/tests/ExpPanelTest.m +++ b/tests/ExpPanelTest.m @@ -1,18 +1,35 @@ classdef (SharedTestFixtures={ % add 'fixtures' folder as test fixture matlab.unittest.fixtures.PathFixture('fixtures'),... - matlab.unittest.fixtures.PathFixture(['fixtures' filesep 'util'])})... - ExpPanelTest < matlab.mock.TestCase + matlab.unittest.fixtures.PathFixture(['fixtures' filesep 'expDefinitions'])})... + ExpPanelTest < matlab.unittest.TestCase properties (SetAccess = protected) % The figure that contains the ExpPanel Parent % Handle for ExpPanel Panel eui.ExpPanel + % Remote Rig object + Remote srv.StimulusControl + % A parameters structure + Parameters + % An experiment reference string + Ref end - + + properties (MethodSetupParameter) + % Experiment type under test + ExpType = {'Base', 'Signals'} % TODO Add tests for ChoiceWorld, etc. + end + methods (TestClassSetup) function setup(testCase) - % SETUP TODO Document + % SETUP Set up test case + % The following occurs during setup: + % 1. Creating parent figure, turn off figure visability and delete + % on taredown. + % 2. Set test flag to true to avoid path in test assertion error. + % 3. Applies repos fixture and create a test subject and expRef. + % 4. Instantiates a StimulusControl object for event listeners. % Hide figures and add teardown function to restore settings def = get(0,'DefaultFigureVisible'); @@ -21,24 +38,115 @@ function setup(testCase) % Create figure for panel testCase.Parent = figure(); + testCase.addTeardown(@delete, testCase.Parent) % Set INTEST flag to true setTestFlag(true); testCase.addTeardown(@setTestFlag, false) + + % Ensure we're using the correct test paths and add teardowns to + % remove any folders we create + testCase.applyFixture(ReposFixture) + + % Now create a single subject folder for testing the log + subject = 'test'; + mainRepo = dat.reposPath('main', 'master'); + assert(mkdir(fullfile(mainRepo, subject)), ... + 'Failed to create subject folder') + testCase.Ref = dat.constructExpRef(subject, now, 1); + + % Set up a StimulusControl object for simulating rig events + testCase.Remote = srv.StimulusControl.create('testRig'); end end methods (TestMethodSetup) - function setupPanel(testCase) -% testCase.ExpPanel = eui.ExpPanel.live(); + function setupParams(testCase, ExpType) + % SETUPPARAMS Set up parameters struct + % Create a parameters structure depending of the ExpType. + + switch lower(ExpType) + case 'signals' + % A Signals experiment without the custom ExpPanel. Instantiates + % the eui.SignalsExpPanel class + testCase.Parameters = struct('type', 'custom', 'defFunction', @nop); + case 'choiceworld' + % ChoiceWorld experiment params. Instantiates the + % eui.ChoiceExpPanel class + testCase.Parameters = exp.choiceWorldParams; + case 'custom' + % Signals experiment params with the expPanelFun parameter. + % Calls the function defined in that parameter + testCase.Parameters = exp.inferParameters(@advancedChoiceWorld); + case 'base' + % Instantiates the eui.ExpPanel base class + testCase.Parameters = struct(... + 'experimentFun', @(pars, rig) nop, ... + 'type', 'unknown'); + case 'barmapping' + % Instantiates the eui.MappingExpPanel class + testCase.Parameters = exp.barMappingParams; + otherwise + testCase.Parameters = []; + end + end + end + + methods (TestMethodTeardown) + function clearFigure(testCase) + % Completely reset the figure on taredown + testCase.Parent = clf(testCase.Parent, 'reset'); end end methods (Test) - function test_panel(testCase) - % TODO Write tests for ExpPanel + function test_live(testCase) + % Test the live constructor method for various experiment types. The + % following things are tested: + % 1. Default update labels + % 2. ActivateLog parameter functionality + % 3. Comments box context menu functionality + % 4. TODO Test comments changed callback + % 5. TODO Check params button function + inputs = { + testCase.Parent; + testCase.Ref; + testCase.Remote; + testCase.Parameters}; + testCase.Panel = eui.ExpPanel.live(inputs{:}, 'ActivateLog', false); + + testCase.fatalAssertTrue(isvalid(testCase.Panel)) + % Test the default labels have been created + % Find all labels + labels = findall(testCase.Parent, 'Style', 'text'); + expected = {'0', '-:--', 'Pending', 'Trial count', 'Elapsed', 'Status'}; + testCase.verifyEqual({labels.String}, expected, 'Default labels incorrect') + comments = findall(testCase.Parent, 'Style', 'edit'); + testCase.assertEmpty(comments, 'Unexpected comments box'); + + % Test build with log activated + delete(testCase.Panel) % Delete previous panel + testCase.Panel = eui.ExpPanel.live(inputs{:}, 'ActivateLog', true); + % Check Comments label exists + labels = findall(testCase.Parent, 'Style', 'text'); + commentsLabel = labels(strcmp({labels.String}, 'Comments')); + testCase.assertNotEmpty(commentsLabel) + % Check comments box exits + comments = findall(testCase.Parent, 'Style', 'edit'); + testCase.assertNotEmpty(comments, 'Failed to create comments box'); + % Test comments box hiding + testCase.assertTrue(strcmp(comments.Visible, 'on')) + menuOption = commentsLabel.UIContextMenu.Children(1); + menuOption.MenuSelectedFcn(menuOption) % Trigger menu callback + testCase.assertTrue(strcmp(comments.Visible, 'off'), 'Failed to hide comments') + menuOption.MenuSelectedFcn(menuOption) % Trigger menu callback + testCase.assertTrue(strcmp(comments.Visible, 'on'), 'Failed to show comments') end +% function test_starttime(testCase) +% % TODO Test Start time input as input (i.e. for reconnect) +% end + end end \ No newline at end of file From cfe8b61ae83afcc46b5f17b996aaed3c0dceb2d9 Mon Sep 17 00:00:00 2001 From: Miles Wells Date: Tue, 28 Jan 2020 17:27:14 +0200 Subject: [PATCH 2/2] Updated CHANGELOG and tests Contents file --- CHANGELOG.md | 1 + tests/Contents.m | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 395f118e..8b03f95f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Starting after Rigbox 2.2.0, this file contains a curated, chronologically order - added guide to creating custom ExpPanels `90294dd` 2019-12-18 - correct behaviour when listening to already running experiments `32a2a17` 2019-12-18 - added support for remote error ids in srv.StimulusControl `9d31eea` 2019-11-27 +- added tests for eui.ExpPanel `572463c` 2020-01-28 ## [2.4.1] diff --git a/tests/Contents.m b/tests/Contents.m index 2f3b4e3a..c9f7d3ce 100644 --- a/tests/Contents.m +++ b/tests/Contents.m @@ -10,6 +10,7 @@ % checkCoverage - Check the coverage of a given test % % AlyxPanel_test - Tests for eui.AlyxPanel +% ExpPanel_test - Tests for eui.ExpPanel % ParamEditor_test - Tests for eui.ParamEditor % Parameters_test - Tests for exp.Parameters % calibrate_test - Tests for hw.calibrate