diff --git a/.github/workflows/moxunit.yml b/.github/workflows/moxunit.yml new file mode 100644 index 00000000..16a9ee9c --- /dev/null +++ b/.github/workflows/moxunit.yml @@ -0,0 +1,32 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + branches: '*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 1 + - name: MOxUnit Action + uses: joergbrech/moxunit-action@v1.1 + with: + tests: tests + src: src + with_coverage: true + cover_xml_file: coverage.xml + - name: Code coverage + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos + file: coverage.xml # optional + flags: unittests # optional + name: codecov-umbrella # optional + fail_ci_if_error: true # optional (default = false) diff --git a/.gitignore b/.gitignore index c1cac9ae..51fd1392 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,25 @@ - +# exclude mac file *DS_Store +# exclude matlab autosaves and octave workspace info *.m~ *octave-workspace # exclude content of logfiles folders +tests/output/* +manualTests/output/* +output/* *.tsv *.mat -check_my_code_report.txt +# exclude temp files from tests and coverage +tests/coverage* +tests/test_code_report.txt test_code_report.txt -output/** +# exclude report from check_my_code +check_my_code_report.txt + + + + diff --git a/.travis.yml b/.travis.yml index 94ba9f97..16d3b453 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,17 +29,19 @@ install: - sudo npm install -g bids-validator before_script: + # Add to src functions to path + - octave $OCTFLAGS --eval "addpath(genpath(fullfile(pwd, 'src'))); savepath ();" # Change current directory - - cd tests + - cd manualTests jobs: include: - - stage: "Tests" - name: "Unit and integration Tests" - script: octave $OCTFLAGS --eval "results = runTests; assert(all(~[results.Failed]))" + # - stage: "Tests" + # name: "Unit and integration Tests" + # script: octave $OCTFLAGS --eval "results = runTests; assert(all(~[results.Failed]))" - stage: "BIDS validator" name: "Create and check dataset" - script: cd manualTests && octave $OCTFLAGS --eval "test_makeRawDataset" && bids-validator `pwd`/output/rawdata/ --ignoreNiftiHeaders + script: octave $OCTFLAGS --eval "test_makeRawDataset" && bids-validator `pwd`/output/rawdata/ --ignoreNiftiHeaders - stage: "Linter" name: "miss_hit" script: cd .. && mh_style `pwd` diff --git a/checkCppBidsDependencies.m b/checkCppBidsDependencies.m deleted file mode 100644 index 898f3c6d..00000000 --- a/checkCppBidsDependencies.m +++ /dev/null @@ -1,27 +0,0 @@ -function checkCppBidsDependencies() - % checkCppBidsDependencies() - % - - pth = fileparts(mfilename('fullpath')); - - checkSubmodule(fullfile(pth, 'lib', 'JSONio')); - checkSubmodule(fullfile(pth, 'lib', 'bids-matlab')); - - addpath(fullfile(pth, 'lib', 'utils')); - addpath(fullfile(pth, 'subfun')); - - printCreditsCppBids(); - -end - -function checkSubmodule(pth) - % If external dir is empty throw an exception - % and ask user to update submodules. - if numel(dir(pth)) <= 2 % Means that the external is empty - error(['Git submodules are not cloned!', ... - 'Try this in your terminal:', ... - ' git submodule update --recursive ']); - else - addpath(pth); - end -end diff --git a/tests/manualTests/miss_hit.cfg b/manualTests/miss_hit.cfg similarity index 100% rename from tests/manualTests/miss_hit.cfg rename to manualTests/miss_hit.cfg diff --git a/tests/testData/eventsDataDictionary.json b/manualTests/testData/eventsDataDictionary.json similarity index 100% rename from tests/testData/eventsDataDictionary.json rename to manualTests/testData/eventsDataDictionary.json diff --git a/manualTests/test_createDataDictionary.m b/manualTests/test_createDataDictionary.m new file mode 100644 index 00000000..d1f71138 --- /dev/null +++ b/manualTests/test_createDataDictionary.m @@ -0,0 +1,55 @@ +function test_suite = test_createDataDictionary %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_createDataDictionaryBasic() + + outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); + + %% set up + + cfg.verbose = false; + + cfg.subject.subjectNb = 1; + cfg.subject.runNb = 1; + + cfg.task.name = 'testtask'; + + cfg.dir.output = outputDir; + + cfg.testingDevice = 'mri'; + + cfg = createFilename(cfg); + + logFile.extraColumns.Speed.length = 1; + logFile.extraColumns.LHL24.length = 3; + logFile = saveEventsFile('init', cfg, logFile); + + createDataDictionary(cfg, logFile); + + %% check that the file has the right path and name + + % data to test against + funcDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'func'); + + jsonFilename = ['sub-001_ses-001_task-testtask_run-001_events_date-' ... + cfg.fileName.date '.json']; + + % test + assertTrue(exist(fullfile(funcDir, jsonFilename), 'file') == 2); + + %% check content + actualStruct = bids.util.jsondecode(fullfile(funcDir, jsonFilename)); + + % data to test against + expectedStruct = bids.util.jsondecode( ... + fullfile(pwd, 'testData', 'eventsDataDictionary.json')); + + % test + assertTrue(isequal(expectedStruct, actualStruct)); + +end diff --git a/tests/manualTests/test_makeRawDataset.m b/manualTests/test_makeRawDataset.m similarity index 92% rename from tests/manualTests/test_makeRawDataset.m rename to manualTests/test_makeRawDataset.m index e3ca4b3d..51b30262 100644 --- a/tests/manualTests/test_makeRawDataset.m +++ b/manualTests/test_makeRawDataset.m @@ -1,9 +1,5 @@ function test_makeRawDataset() - fprintf('\n\n--------------------------------------------------------------------\n\n'); - - clear; - outputDir = fullfile(fileparts(mfilename('fullpath')), 'output'); if isdir(outputDir) @@ -16,7 +12,9 @@ function test_makeRawDataset() cfg.subject.subjectNb = 1; cfg.subject.runNb = 1; + cfg.task.name = 'testtask'; + cfg.dir.output = outputDir; cfg.bids.datasetDescription.Name = 'dummy'; @@ -77,7 +75,7 @@ function test_makeRawDataset() funcDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'func'); boldFilename = 'sub-001_ses-001_task-testtask_run-001_bold.nii.gz'; copyfile( ... - fullfile('..', '..', 'dummyData', 'dummyData.nii.gz'), ... + fullfile('..', 'dummyData', 'dummyData.nii.gz'), ... fullfile(funcDir, boldFilename)); %% diff --git a/tests/manualTests/test_userInput.m b/manualTests/test_userInput.m similarity index 100% rename from tests/manualTests/test_userInput.m rename to manualTests/test_userInput.m diff --git a/printCreditsCppBids.m b/printCreditsCppBids.m deleted file mode 100644 index bfb3f252..00000000 --- a/printCreditsCppBids.m +++ /dev/null @@ -1,44 +0,0 @@ -function printCreditsCppBids() - - version = '0.0.1'; - - contributors = { ... - 'Rémi Gau', ... - 'Marco Barilari', ... - 'Ceren Battal'}; - - % DOI_URL = 'https://doi.org/10.5281/zenodo.3554331.'; - - repoURL = 'https://github.com/cpp-lln-lab/CPP_BIDS'; - - fprintf('\n\n'); - - disp('___________________________________________________'); - disp('___________________________________________________'); - disp(' '); - disp(' ___ ___ ___ ___ ___ ___ ___ '); - disp(' / __| _ \ _ \ | _ )_ _| \/ __|'); - disp(' | (__| _/ _/ | _ \| || |) \__ \'); - disp(' \___|_| |_| |___/___|___/|___/'); - disp(' '); - - splash = 'Thank you for using the CPP BIDS - version %s. '; - fprintf(splash, version); - fprintf('\n\n'); - - fprintf('Current list of contributors includes:\n'); - for iCont = 1:numel(contributors) - fprintf(' %s\n', contributors{iCont}); - end - fprintf('\b\n\n'); - - % fprintf('Please cite using the following DOI: \n %s\n\n', DOI_URL) - - fprintf('For bug report, suggestions or contributions see: \n %s\n\n', repoURL); - - disp('___________________________________________________'); - disp('___________________________________________________'); - - fprintf('\n\n'); - -end diff --git a/checkCFG.m b/src/checkCFG.m similarity index 98% rename from checkCFG.m rename to src/checkCFG.m index 10337a5d..a1563897 100644 --- a/checkCFG.m +++ b/src/checkCFG.m @@ -4,13 +4,13 @@ % check that we have all the fields that we need in the experiment parameters % reuses a lot of code from the BIDS starter kit - checkCppBidsDependencies(); - if nargin < 1 || isempty(cfg) cfg = struct(); end - %% set the cfg defaults + checkCppBidsDependencies(cfg); + + %% list the defaults to set fieldsToSet.verbose = false; @@ -43,6 +43,7 @@ fieldsToSet = transferInfoToBids(fieldsToSet, cfg); + %% Set defaults cfg = setDefaultFields(cfg, fieldsToSet); end diff --git a/src/checkCppBidsDependencies.m b/src/checkCppBidsDependencies.m new file mode 100644 index 00000000..03dfd92f --- /dev/null +++ b/src/checkCppBidsDependencies.m @@ -0,0 +1,39 @@ +function checkCppBidsDependencies(cfg) + % checkCppBidsDependencies() + % + + GITHUB_WORKSPACE = getenv('GITHUB_WORKSPACE'); + + if strcmp(GITHUB_WORKSPACE, '/github/workspace') + + pth = GITHUB_WORKSPACE; + addpath(fullfile(pth, 'lib', 'JSONio')); + addpath(fullfile(pth, 'lib', 'bids-matlab')); + + elseif isempty(GITHUB_WORKSPACE) % local + + pth = fullfile(fileparts(mfilename('fullpath')), '..'); + checkSubmodule(fullfile(pth, 'lib', 'JSONio')); + checkSubmodule(fullfile(pth, 'lib', 'bids-matlab')); + + addpath(fullfile(pth, 'src', 'subfun')); + + end + + addpath(fullfile(pth, 'lib', 'utils')); + + printCreditsCppBids(cfg); + +end + +function checkSubmodule(pth) + % If external dir is empty throw an exception + % and ask user to update submodules. + if numel(dir(pth)) <= 2 % Means that the external is empty + error(['Git submodules are not cloned!', ... + 'Try this in your terminal:', ... + ' git submodule update --recursive ']); + else + addpath(pth); + end +end diff --git a/convertSourceToRaw.m b/src/convertSourceToRaw.m similarity index 92% rename from convertSourceToRaw.m rename to src/convertSourceToRaw.m index e6e7df5a..bc73606a 100644 --- a/convertSourceToRaw.m +++ b/src/convertSourceToRaw.m @@ -6,17 +6,17 @@ function convertSourceToRaw(cfg) % - creates dummy README and CHANGE file % - copy source dir to raw dir % - remove the date suffix (_date-YYYYMMDDHHMM) from the files where it is present - % + % sourceDir = fullfile(cfg.dir.output, 'source'); rawDir = fullfile(cfg.dir.output, 'rawdata'); % add dummy readme and change file copyfile(fullfile( ... - fileparts(mfilename('fullpath')), 'dummyData', 'README'), ... + fileparts(mfilename('fullpath')), '..', 'dummyData', 'README'), ... sourceDir); copyfile(fullfile( ... - fileparts(mfilename('fullpath')), 'dummyData', 'CHANGES'), ... + fileparts(mfilename('fullpath')), '..', 'dummyData', 'CHANGES'), ... sourceDir); copyfile(sourceDir, rawDir); diff --git a/createBoldJson.m b/src/createBoldJson.m similarity index 100% rename from createBoldJson.m rename to src/createBoldJson.m diff --git a/createDataDictionary.m b/src/createDataDictionary.m similarity index 100% rename from createDataDictionary.m rename to src/createDataDictionary.m diff --git a/createDatasetDescription.m b/src/createDatasetDescription.m similarity index 100% rename from createDatasetDescription.m rename to src/createDatasetDescription.m diff --git a/createFilename.m b/src/createFilename.m similarity index 89% rename from createFilename.m rename to src/createFilename.m index 88469cc8..8f73628a 100644 --- a/createFilename.m +++ b/src/createFilename.m @@ -177,19 +177,23 @@ function talkToMe(cfg) - fprintf(1, '\nData will be saved in this directory:\n\t%s\n', ... - fullfile(cfg.dir.outputSubject, cfg.fileName.modality)); + if cfg.verbose - fprintf(1, '\nData will be saved in this file:\n\t%s\n', ... - cfg.fileName.events); + fprintf(1, '\nData will be saved in this directory:\n\t%s\n', ... + fullfile(cfg.dir.outputSubject, cfg.fileName.modality)); - if cfg.eyeTracker.do + fprintf(1, '\nData will be saved in this file:\n\t%s\n', ... + cfg.fileName.events); + + if cfg.eyeTracker.do - fprintf(1, '\nEyetracking data will be saved in this directory:\n\t%s\n', ... - fullfile(cfg.dir.outputSubject, 'eyetracker')); + fprintf(1, '\nEyetracking data will be saved in this directory:\n\t%s\n', ... + fullfile(cfg.dir.outputSubject, 'eyetracker')); - fprintf(1, '\nEyetracking data will be saved in this file:\n\t%s\n', ... - cfg.fileName.eyetracker); + fprintf(1, '\nEyetracking data will be saved in this file:\n\t%s\n', ... + cfg.fileName.eyetracker); + + end end diff --git a/src/miss_hit.cfg b/src/miss_hit.cfg new file mode 100644 index 00000000..fce7fa45 --- /dev/null +++ b/src/miss_hit.cfg @@ -0,0 +1,3 @@ +line_length: 100 +regex_function_name: "[a-z]+(([A-Z]){1}[A-Za-z]+)*" +suppress_rule: "copyright_notice" \ No newline at end of file diff --git a/src/printCreditsCppBids.m b/src/printCreditsCppBids.m new file mode 100644 index 00000000..ab1e19d8 --- /dev/null +++ b/src/printCreditsCppBids.m @@ -0,0 +1,53 @@ +function printCreditsCppBids(cfg) + + verbose = true; + if ~isempty(cfg) && isfield(cfg, 'verbose') && ~isempty(cfg.verbose) + verbose = cfg.verbose; + end + + if verbose + + version = '0.0.1'; + + contributors = { ... + 'Rémi Gau', ... + 'Marco Barilari', ... + 'Ceren Battal'}; + + % DOI_URL = 'https://doi.org/10.5281/zenodo.3554331.'; + + repoURL = 'https://github.com/cpp-lln-lab/CPP_BIDS'; + + fprintf('\n\n'); + + disp('___________________________________________________'); + disp('___________________________________________________'); + disp(' '); + disp(' ___ ___ ___ ___ ___ ___ ___ '); + disp(' / __| _ \ _ \ | _ )_ _| \/ __|'); + disp(' | (__| _/ _/ | _ \| || |) \__ \'); + disp(' \___|_| |_| |___/___|___/|___/'); + disp(' '); + + splash = 'Thank you for using the CPP BIDS - version %s. '; + fprintf(splash, version); + fprintf('\n\n'); + + fprintf('Current list of contributors includes:\n'); + for iCont = 1:numel(contributors) + fprintf(' %s\n', contributors{iCont}); + end + fprintf('\b\n\n'); + + % fprintf('Please cite using the following DOI: \n %s\n\n', DOI_URL) + + fprintf('For bug report, suggestions or contributions see: \n %s\n\n', repoURL); + + disp('___________________________________________________'); + disp('___________________________________________________'); + + fprintf('\n\n'); + + end + +end diff --git a/saveEventsFile.m b/src/saveEventsFile.m similarity index 96% rename from saveEventsFile.m rename to src/saveEventsFile.m index 624b17dd..5f7388e9 100644 --- a/saveEventsFile.m +++ b/src/saveEventsFile.m @@ -88,11 +88,7 @@ % close txt log file fclose(logFile(1).fileID); - fprintf(1, '\nData were saved in this file:\n\n%s\n\n', ... - fullfile( ... - cfg.dir.outputSubject, ... - cfg.fileName.modality, ... - logFile.filename)); + talkToMe(cfg, logFile); otherwise @@ -357,3 +353,17 @@ function errorSaveEventsFile(identifier) errorStruct.identifier = ['saveEventsFile:' identifier]; error(errorStruct); end + +function talkToMe(cfg, logFile) + + if cfg.verbose + + fprintf(1, '\nData were saved in this file:\n\n%s\n\n', ... + fullfile( ... + cfg.dir.outputSubject, ... + cfg.fileName.modality, ... + logFile.filename)); + + end + +end diff --git a/subfun/createTaskName.m b/src/subfun/createTaskName.m similarity index 100% rename from subfun/createTaskName.m rename to src/subfun/createTaskName.m diff --git a/subfun/initializeExtraColumns.m b/src/subfun/initializeExtraColumns.m similarity index 100% rename from subfun/initializeExtraColumns.m rename to src/subfun/initializeExtraColumns.m diff --git a/subfun/returnHeaderName.m b/src/subfun/returnHeaderName.m similarity index 98% rename from subfun/returnHeaderName.m rename to src/subfun/returnHeaderName.m index 1caff806..2401ea0d 100644 --- a/subfun/returnHeaderName.m +++ b/src/subfun/returnHeaderName.m @@ -1,7 +1,7 @@ function headerName = returnHeaderName(columnName, nbCol, iCol) % headerName = returnHeaderName(columnName, nbCol, iCol) % - + if nbCol == 1 headerName = sprintf('%s', columnName); else diff --git a/subfun/returnNamesExtraColumns.m b/src/subfun/returnNamesExtraColumns.m similarity index 98% rename from subfun/returnNamesExtraColumns.m rename to src/subfun/returnNamesExtraColumns.m index 502d2e57..ada0791c 100644 --- a/subfun/returnNamesExtraColumns.m +++ b/src/subfun/returnNamesExtraColumns.m @@ -1,7 +1,7 @@ function [namesExtraColumns, logFile] = returnNamesExtraColumns(logFile) % [namesExtraColumns, logFile] = returnNamesExtraColumns(logFile) % - + namesExtraColumns = []; if isfield(logFile, 'extraColumns') && ~isempty(logFile(1).extraColumns) diff --git a/subfun/returnNbColumns.m b/src/subfun/returnNbColumns.m similarity index 100% rename from subfun/returnNbColumns.m rename to src/subfun/returnNbColumns.m diff --git a/subfun/setDefaultFields.m b/src/subfun/setDefaultFields.m similarity index 100% rename from subfun/setDefaultFields.m rename to src/subfun/setDefaultFields.m diff --git a/subfun/transferInfoToBids.m b/src/subfun/transferInfoToBids.m similarity index 100% rename from subfun/transferInfoToBids.m rename to src/subfun/transferInfoToBids.m diff --git a/userInputs.m b/src/userInputs.m similarity index 100% rename from userInputs.m rename to src/userInputs.m diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..673cc339 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,97 @@ +# how to run the tests + +- Install [MOxUnit for matlab and octave](https://github.com/MOxUnit/MOxUnit) to run the tests +- Install [MOcov for matlab and octave](https://github.com/MOcov/MOcov) to get the code coverage +- Make sure you are in the `tests` directory. +- Run `moxunit_runtests` or `moxunit_runtests -verbose` to run the tests. + +This should tell you which tests pass or fail. + +## code coverage + +The following command would give more info and will give you HTML output in a `coverage_html` folder +showing you which lines of code is or is not checked by your test suite. + +``` matlab +success = moxunit_runtests(pwd, ... % the path where the tests are + '-verbose', ... + '-with_coverage', ... + '-cover', fullfile(pwd, '..'), ... % the path of the code whose coverage we want to estimate + '-cover_xml_file','coverage.xml', ... + '-cover_html_dir','coverage_html'); +``` +This will return a clear underestimation of the code coverage as the the code in dependencies in the `lib` folder +are also included in this report. + +If you want to get a slightly more accurate estimate you should run the following. + +I have not been able to find a way to exclude certain files without breaking some tests. + +```matlab +coverage = mocov( ... + '-expression', 'moxunit_runtests()', ... + '-verbose', ... + '-cover', fullfile(pwd, '..'), ... + '-cover_exclude', '*jsonread.m', ... + '-cover_exclude', '*json*code.m', ... + '-cover_exclude', '*Contents.m', ... + '-cover_exclude', '*report.m', ... + '-cover_exclude', '*layout.m', ... + '-cover_exclude', '*query.m', ... + '-cover_exclude', '*private*', ... + '-cover_exclude', '*util*', ... + '-cover_exclude', '*Tests*', ... + '-cover_exclude', '*tests*', ... + '-cover_exclude', '*test_*', ... + '-cover_xml_file','coverage.xml', ... + '-cover_html_dir','coverage_html') +``` + + +## Adding more tests + +You can use the following function template to write more tests. + + +```matlab +function test_suite = test_functionToTest() + % This top function is necessary for mox unit to run tests. + % DO NOT CHANGE IT except to adapt the name of the function. + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_functionToTestBasic() + + %% set up + + + %% data to test against + + + %% test + % assertTrue( ); + % assertFalse( ); + % assertEqual( ); + +end + +function test_functionToTestUseCase1() + + %% set up + + + %% data to test against + + + %% test + % assertTrue( ); + % assertFalse( ); + % assertEqual( ); + +end +``` + diff --git a/tests/runTests.m b/tests/runTests.m deleted file mode 100644 index 77ceecec..00000000 --- a/tests/runTests.m +++ /dev/null @@ -1,63 +0,0 @@ -function results = runTests(pth) - % Run tests - % List all the 'test_*.m' files located in the same directory as this - % function, run them and keep track of how many passed, failed or are - % incomplete. - % __________________________________________________________________________ - - % Copyright (C) 2019, Guillaume Flandin, Wellcome Centre for Human Neuroimaging - % Copyright (C) 2020--, CPP_BIDS developers - - % -Get the path of where this file is located - if ~nargin - pth = fileparts(mfilename('fullpath')); - end - - % -List all the 'test_*.m' files located in the same directory as this - % function - d = dir(pth); - d([d.isdir]) = []; - d(arrayfun(@(x) isempty(regexp(x.name, '^test_.*\.m$', 'once')), d)) = []; - - results = struct('Passed', {}, 'Failed', {}, 'Incomplete', {}, 'Duration', {}); - for i = 1:numel(d) - - results(i).Failed = false; - results(i).Passed = false; - results(i).Incomplete = false; - - tstart = tic; - - % -Run each test file and catch error message in case of failure - try - fprintf('\n\n--------------------------------------------------------------------\n'); - fprintf('%s', d(i).name(1:end - 2)); - fprintf('\n--------------------------------------------------------------------\n'); - feval(d(i).name(1:end - 2)); - results(i).Passed = true; - - catch err - results(i).Failed = true; - fprintf('\n%s', err.message); - end - - results(i).Duration = toc(tstart); - - fprintf('\n'); - - end - - if ~nargout - fprintf(['Totals (%d tests):\n\t%d Passed, %d Failed, %d Incomplete.\n' ... - '\t%f seconds testing time.\n\n'], numel(results), nnz([results.Passed]), ... - nnz([results.Failed]), nnz([results.Incomplete]), sum([results.Duration])); - for i = 1:numel(d) - status = 'Incomplete'; - if results(i).Passed - status = 'Passed'; - elseif results(i).Failed - status = 'Failed'; - end - fprintf('%s: %s\n', d(i).name(1:end - 2), status); - end - end diff --git a/tests/test_checkCFG.m b/tests/test_checkCFG.m index 8c2155ed..f82a1171 100644 --- a/tests/test_checkCFG.m +++ b/tests/test_checkCFG.m @@ -1,21 +1,34 @@ -function test_checkCFG() +function test_suite = test_checkCFG %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_checkCfgDefault() + %% set up cfg.dir.output = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); cfg = checkCFG(cfg); - expectedStructure = returnExpectedStructure(); + %% create test data + expectedStructure = returnExpectedCfgStructure(); expectedStructure.dir.output = cfg.dir.output; expectedStructure.testingDevice = 'pc'; - testSubFields(expectedStructure, cfg); + %% test + checkSubFields(expectedStructure, cfg); - %% - fprintf('\n--------------------------------------------------------------------'); +end - clear; +function test_checkCfgBasic() + %% set up outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); + cfg.verbose = false; + cfg.subject.subjectNb = 1; cfg.subject.runNb = 1; @@ -33,10 +46,8 @@ function test_checkCFG() cfg = checkCFG(cfg); - %%% test - - % test data - expectedStructure = returnExpectedStructure(); + %% create test data + expectedStructure = returnExpectedCfgStructure(); expectedStructure.subject.subjectNb = 1; expectedStructure.subject.runNb = 1; @@ -61,68 +72,67 @@ function test_checkCFG() expectedStructure = orderfields(expectedStructure); - testSubFields(expectedStructure, cfg); - - fprintf('\n'); + %% test + checkSubFields(expectedStructure, cfg); end -function expectedStructure = returnExpectedStructure() - - expectedStructure.subject.subjectGrp = ''; - expectedStructure.subject.sessionNb = 1; - expectedStructure.subject.askGrpSess = [true true]; - - expectedStructure.verbose = 0; - - expectedStructure.fileName.task = ''; - expectedStructure.fileName.zeroPadding = 3; - expectedStructure.fileName.dateFormat = 'yyyymmddHHMM'; - - expectedStructure.eyeTracker.do = false; - - expectedStructure.mri.contrastEnhancement = []; - expectedStructure.mri.phaseEncodingDirection = []; - expectedStructure.mri.reconstruction = []; - expectedStructure.mri.echo = []; - expectedStructure.mri.acquisition = []; - expectedStructure.mri.repetitionTime = []; - - expectedStructure.bids.mri.RepetitionTime = []; - expectedStructure.bids.mri.SliceTiming = ''; - expectedStructure.bids.mri.TaskName = ''; - expectedStructure.bids.mri.Instructions = ''; - expectedStructure.bids.mri.TaskDescription = ''; - - expectedStructure.bids.meg.TaskName = ''; - expectedStructure.bids.meg.SamplingFrequency = []; - expectedStructure.bids.meg.PowerLineFrequency = []; - expectedStructure.bids.meg.DewarPosition = []; - expectedStructure.bids.meg.SoftwareFilters = []; - expectedStructure.bids.meg.DigitizedLandmarks = []; - expectedStructure.bids.meg.DigitizedHeadPoints = []; - - expectedStructure.bids.datasetDescription.Name = ''; - expectedStructure.bids.datasetDescription.BIDSVersion = ''; - expectedStructure.bids.datasetDescription.License = ''; - expectedStructure.bids.datasetDescription.Authors = {''}; - expectedStructure.bids.datasetDescription.Acknowledgements = ''; - expectedStructure.bids.datasetDescription.HowToAcknowledge = ''; - expectedStructure.bids.datasetDescription.Funding = {''}; - expectedStructure.bids.datasetDescription.ReferencesAndLinks = {''}; - expectedStructure.bids.datasetDescription.DatasetDOI = ''; - - expectedStructure = orderfields(expectedStructure); +function expectedCfgStructure = returnExpectedCfgStructure() + + expectedCfgStructure.subject.subjectGrp = ''; + expectedCfgStructure.subject.sessionNb = 1; + expectedCfgStructure.subject.askGrpSess = [true true]; + + expectedCfgStructure.verbose = 0; + + expectedCfgStructure.fileName.task = ''; + expectedCfgStructure.fileName.zeroPadding = 3; + expectedCfgStructure.fileName.dateFormat = 'yyyymmddHHMM'; + + expectedCfgStructure.eyeTracker.do = false; + + expectedCfgStructure.mri.contrastEnhancement = []; + expectedCfgStructure.mri.phaseEncodingDirection = []; + expectedCfgStructure.mri.reconstruction = []; + expectedCfgStructure.mri.echo = []; + expectedCfgStructure.mri.acquisition = []; + expectedCfgStructure.mri.repetitionTime = []; + + expectedCfgStructure.bids.mri.RepetitionTime = []; + expectedCfgStructure.bids.mri.SliceTiming = ''; + expectedCfgStructure.bids.mri.TaskName = ''; + expectedCfgStructure.bids.mri.Instructions = ''; + expectedCfgStructure.bids.mri.TaskDescription = ''; + + expectedCfgStructure.bids.meg.TaskName = ''; + expectedCfgStructure.bids.meg.SamplingFrequency = []; + expectedCfgStructure.bids.meg.PowerLineFrequency = []; + expectedCfgStructure.bids.meg.DewarPosition = []; + expectedCfgStructure.bids.meg.SoftwareFilters = []; + expectedCfgStructure.bids.meg.DigitizedLandmarks = []; + expectedCfgStructure.bids.meg.DigitizedHeadPoints = []; + + expectedCfgStructure.bids.datasetDescription.Name = ''; + expectedCfgStructure.bids.datasetDescription.BIDSVersion = ''; + expectedCfgStructure.bids.datasetDescription.License = ''; + expectedCfgStructure.bids.datasetDescription.Authors = {''}; + expectedCfgStructure.bids.datasetDescription.Acknowledgements = ''; + expectedCfgStructure.bids.datasetDescription.HowToAcknowledge = ''; + expectedCfgStructure.bids.datasetDescription.Funding = {''}; + expectedCfgStructure.bids.datasetDescription.ReferencesAndLinks = {''}; + expectedCfgStructure.bids.datasetDescription.DatasetDOI = ''; + + expectedCfgStructure = orderfields(expectedCfgStructure); end -function testSubFields(expectedStructure, cfg) +function checkSubFields(expectedStructure, cfg) % check that that the structures match % if it fails it check from which subfield the error comes from try - assert(isequal(expectedStructure, cfg)); + assertEqual(expectedStructure, cfg); catch ME @@ -139,8 +149,8 @@ function testSubFields(expectedStructure, cfg) end - expectedStructure; - cfg; + disp(expectedStructure); + disp(cfg); rethrow(ME); end diff --git a/tests/test_createBoldJson.m b/tests/test_createBoldJson.m index 72348bfa..769d7148 100644 --- a/tests/test_createBoldJson.m +++ b/tests/test_createBoldJson.m @@ -1,15 +1,26 @@ -function test_createBoldJson() +function test_suite = test_createBoldJson %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_createBoldJsonBasic() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up part + %% set up + + cfg.verbose = false; cfg.subject.subjectNb = 1; cfg.subject.runNb = 1; + cfg.task.name = 'testtask'; + cfg.dir.output = outputDir; - % cfg = struct(); cfg.testingDevice = 'mri'; cfg = createFilename(cfg); @@ -18,14 +29,13 @@ function test_createBoldJson() createBoldJson(cfg); - %%% test part - - % test data + %% data to test against funcDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'func'); + eventFilename = ['sub-001_ses-001_task-testtask_run-001_bold_date-' ... cfg.fileName.date '.json']; - % check that the file has the right path and name - assert(exist(fullfile(funcDir, eventFilename), 'file') == 2); + %% test + assertTrue(exist(fullfile(funcDir, eventFilename), 'file') == 2); end diff --git a/tests/test_createDataDictionary.m b/tests/test_createDataDictionary.m deleted file mode 100644 index c9bf1a81..00000000 --- a/tests/test_createDataDictionary.m +++ /dev/null @@ -1,40 +0,0 @@ -function test_createDataDictionary() - - clear; - - outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - - %%% set up part - - cfg.subject.subjectNb = 1; - cfg.subject.runNb = 1; - cfg.task.name = 'testtask'; - cfg.dir.output = outputDir; - - cfg.testingDevice = 'mri'; - - cfg = createFilename(cfg); - - logFile.extraColumns.Speed.length = 1; - logFile.extraColumns.LHL24.length = 3; - logFile = saveEventsFile('init', cfg, logFile); - - createDataDictionary(cfg, logFile); - - %%% test part - - % test data - funcDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'func'); - jsonFilename = ['sub-001_ses-001_task-testtask_run-001_events_date-' ... - cfg.fileName.date '.json']; - - % check that the file has the right path and name - assert(exist(fullfile(funcDir, jsonFilename), 'file') == 2); - - % check content - expectedStruct = bids.util.jsondecode(fullfile(pwd, 'testData', 'eventsDataDictionary.json')); - actualStruct = bids.util.jsondecode(fullfile(funcDir, jsonFilename)); - - assert(isequal(expectedStruct, actualStruct)); - -end diff --git a/tests/test_createDatasetDescription.m b/tests/test_createDatasetDescription.m index 629fe432..c4664eb0 100644 --- a/tests/test_createDatasetDescription.m +++ b/tests/test_createDatasetDescription.m @@ -1,11 +1,21 @@ -function test_createDatasetDescription() +function test_suite = test_createDatasetDescription %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_createDatasetDescriptionBasic() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up part + %% set up cfg.dir.output = outputDir; + cfg.verbose = false; + cfg.bids.datasetDescription.json.Name = 'dummy_dataset'; cfg.bids.datasetDescription.json.BIDSVersion = '1.0.0'; cfg.bids.datasetDescription.json.License = 'none'; @@ -15,13 +25,11 @@ function test_createDatasetDescription() createDatasetDescription(cfg); - %%% test part - - % test data + %% data to test against directory = fullfile(outputDir, 'source'); filename = 'dataset_description.json'; - % check that the file has the right path and name - assert(exist(fullfile(directory, filename), 'file') == 2); + %% test + assertTrue(exist(fullfile(directory, filename), 'file') == 2); end diff --git a/tests/test_createFilename.m b/tests/test_createFilename.m index ebce891f..772a536a 100644 --- a/tests/test_createFilename.m +++ b/tests/test_createFilename.m @@ -1,51 +1,59 @@ -function test_createFilename() - % test for filename creation and their directories +function test_suite = test_createFilename %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end - %% PC +function test_createFilenameBasic() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up part + %% set up + cfg.verbose = false; cfg.subject.subjectNb = 1; cfg.subject.runNb = 1; cfg.task.name = 'test task'; cfg.dir.output = outputDir; - %%% run part cfg = createFilename(cfg); - %%% test part - - % test data + %% data to test against behDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'beh'); + eyetrackerDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'eyetracker'); + eventFilename = ['sub-001_ses-001_task-testTask_run-001_events_date-'... cfg.fileName.date '.tsv']; + stimFilename = ['sub-001_ses-001_task-testTask_run-001_stim_date-'... cfg.fileName.date '.tsv']; + %% test + % make sure the beh dir is created - assert(exist(behDir, 'dir') == 7); + assertTrue(exist(behDir, 'dir') == 7); % make sure the eyetracker dir is not created - assert(exist(eyetrackerDir, 'dir') == 0); + assertTrue(exist(eyetrackerDir, 'dir') == 0); % make sure the events filename is created - assert(strcmp(cfg.fileName.events, eventFilename)); + assertEqual(cfg.fileName.events, eventFilename); % make sure the stim filename is created - assert(strcmp(cfg.fileName.stim, stimFilename)); + assertEqual(cfg.fileName.stim, stimFilename); - %% fMRI and eye tracker - fprintf('\n--------------------------------------------------------------------'); +end - clear; +function test_createFilenameMriEyetracker() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up part + %% set up + cfg.verbose = false; cfg.subject.subjectGrp = 'ctrl'; cfg.subject.subjectNb = 2; cfg.subject.sessionNb = 2; @@ -58,37 +66,41 @@ function test_createFilename() cfg = createFilename(cfg); - %%% test part + %% data to test against - % test data funcDir = fullfile(outputDir, 'source', 'sub-ctrl002', 'ses-002', 'func'); + eyetrackerDir = fullfile(outputDir, 'source', 'sub-ctrl002', 'ses-002', 'eyetracker'); + baseFilename = 'sub-ctrl002_ses-002_task-testTask'; + eventFilename = ['sub-ctrl002_ses-002_task-testTask_run-002_events_date-' ... cfg.fileName.date '.tsv']; + eyetrackerFilename = ['sub-ctrl002_ses-002_task-testTask_run-002_eyetrack_date-' ... cfg.fileName.date '.edf']; + %% tests % make sure the func dir is created - assert(exist(funcDir, 'dir') == 7); + assertTrue(exist(funcDir, 'dir') == 7); % make sure the eyetracker dir is created - assert(exist(eyetrackerDir, 'dir') == 7); + assertTrue(exist(eyetrackerDir, 'dir') == 7); % make sure the right filenames are created - assert(strcmp(cfg.fileName.base, baseFilename)); - assert(strcmp(cfg.fileName.events, eventFilename)); - assert(strcmp(cfg.fileName.eyetracker, eyetrackerFilename)); + assertEqual(cfg.fileName.base, baseFilename); + assertEqual(cfg.fileName.events, eventFilename); + assertEqual(cfg.fileName.eyetracker, eyetrackerFilename); - %% EEG - fprintf('\n--------------------------------------------------------------------'); +end - clear; +function test_createFilenameEeg() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up part + %% set up + cfg.verbose = false; cfg.subject.subjectGrp = 'blind'; cfg.subject.subjectNb = 3; cfg.subject.sessionNb = 1; @@ -100,10 +112,11 @@ function test_createFilename() cfg = createFilename(cfg); - %%% test part - - % test data + %% data to test against eegDir = fullfile(outputDir, 'source', 'sub-blind003', 'ses-001', 'eeg'); + %% test % make sure the func dir is created - assert(exist(eegDir, 'dir') == 7); + assertTrue(exist(eegDir, 'dir') == 7); + +end diff --git a/tests/test_createTaskName.m b/tests/test_createTaskName.m index 6f30fe35..f3aac9a4 100644 --- a/tests/test_createTaskName.m +++ b/tests/test_createTaskName.m @@ -1,5 +1,14 @@ -function test_createTaskName() - % +function test_suite = test_createTaskName %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_createTaskNameRemoveInvalidCharacters() + + %% set up taskName = '&|@#-_(§!{})[]ù%£+/=:;.?,\<> visual task'; @@ -7,15 +16,18 @@ function test_createTaskName() [unvalidCharacters] = regexp(taskNameValid, '[^a-zA-Z0-9]'); - assert(isempty(unvalidCharacters)); + %% test + assertTrue(isempty(unvalidCharacters)); + %% set up taskName = ' 09 visual task'; [taskName, taskNameValid] = createTaskName(taskName); [unvalidCharacters] = regexp(taskNameValid, '[^a-zA-Z0-9]'); - assert(isempty(unvalidCharacters)); + %% test + assertTrue(isempty(unvalidCharacters)); taskName = 'foo bar'; [taskName, taskNameValid] = createTaskName(taskName); @@ -23,3 +35,15 @@ function test_createTaskName() assert(isequal(taskNameValid, 'fooBar')); end + +function test_createTaskNameCamelCase() + + %% set up + taskName = 'foo bar'; + [taskName, taskNameValid] = createTaskName(taskName); + + %% test + assertEqual(taskName, 'foo Bar'); + assertEqual(taskNameValid, 'fooBar'); + +end diff --git a/tests/test_saveEventsFileInit.m b/tests/test_saveEventsFileInit.m index ca0ecf02..d56fe165 100644 --- a/tests/test_saveEventsFileInit.m +++ b/tests/test_saveEventsFileInit.m @@ -1,55 +1,69 @@ -function test_saveEventsFileInit() +function test_suite = test_saveEventsFileInit %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_saveEventsFileInitBasic() + + %% set up - %% + cfg.verbose = false; - %%% set up % make sure the dependencies are there - checkCFG(); + checkCFG(cfg); - %%% do stuff [logFile] = saveEventsFile('init'); - %%% test section + %% data to test against expectedStrcut(1).filename = ''; expectedStrcut(1).extraColumns = []; - assert(isequal(expectedStrcut, logFile)); + %% test + assertEqual(expectedStrcut, logFile); + +end + +function test_saveEventsFileInitExtraColumns() - %% - fprintf('\n--------------------------------------------------------------------'); + %% set up - clear; + cfg.verbose = false; + + cfg = checkCFG(cfg); - %%% set up - cfg = checkCFG(); logFile.extraColumns = {'Speed'}; - %%% do stuff [logFile] = saveEventsFile('init', cfg, logFile); - %%% test section + %% data to test against expectedStrcut(1).extraColumns.Speed.length = 1; expectedStrcut(1).extraColumns.Speed.bids.LongName = ''; expectedStrcut(1).extraColumns.Speed.bids.Description = ''; expectedStrcut(1).extraColumns.Speed.bids.Levels = ''; expectedStrcut(1).extraColumns.Speed.bids.TermURL = ''; - assert(isequal(expectedStrcut, logFile)); + %% test + assertEqual(expectedStrcut, logFile); + +end + +function test_saveEventsFileInitExtraColumnsArray() + + %% set up - %% - fprintf('\n--------------------------------------------------------------------'); + cfg.verbose = false; - clear; + cfg = checkCFG(cfg); - %%% set up - cfg = checkCFG(); logFile.extraColumns.Speed.length = 1; logFile.extraColumns.LHL24.length = 3; - %%% do stuff [logFile] = saveEventsFile('init', cfg, logFile); - %%% test section + %% data to test against expectedStrcut(1).extraColumns.Speed.length = 1; expectedStrcut(1).extraColumns.Speed.bids.LongName = ''; expectedStrcut(1).extraColumns.Speed.bids.Description = ''; @@ -61,8 +75,7 @@ function test_saveEventsFileInit() expectedStrcut(1).extraColumns.LHL24.bids.Levels = ''; expectedStrcut(1).extraColumns.LHL24.bids.TermURL = ''; - assert(isequal(expectedStrcut, logFile)); - - fprintf('\n'); + %% test + assertEqual(expectedStrcut, logFile); end diff --git a/tests/test_saveEventsFileOpen.m b/tests/test_saveEventsFileOpen.m index 032f5f47..134f6ffe 100644 --- a/tests/test_saveEventsFileOpen.m +++ b/tests/test_saveEventsFileOpen.m @@ -1,21 +1,28 @@ -function test_saveEventsFileOpen() +function test_suite = test_saveEventsFileOpen %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end - %% Initialize file - clear; +function test_saveEventsFileOpenBasic() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up + %% set up + + cfg.verbose = false; cfg.subject.subjectNb = 1; cfg.subject.runNb = 1; + cfg.task.name = 'testtask'; + cfg.dir.output = outputDir; cfg.testingDevice = 'mri'; - %%% do stuff - cfg = createFilename(cfg); % create the events file and header @@ -24,9 +31,7 @@ function test_saveEventsFileOpen() % close the file saveEventsFile('close', cfg, logFile); - %%% test section - - % test data + %% data to test against funcDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'func'); eventFilename = ['sub-001_ses-001_task-testtask_run-001_events_date-' ... cfg.fileName.date '.tsv']; @@ -37,41 +42,45 @@ function test_saveEventsFileOpen() FID = fopen(fullfile(funcDir, eventFilename), 'r'); C = textscan(FID, repmat('%s', 1, 3), 'Delimiter', '\t', 'EndOfLine', '\n'); + %% test % check the extra columns of the header - assert(isequal(C{1}{1}, 'onset')); - assert(isequal(C{2}{1}, 'duration')); - assert(isequal(C{3}{1}, 'trial_type')); + assertEqual(C{1}{1}, 'onset'); + assertEqual(C{2}{1}, 'duration'); + assertEqual(C{3}{1}, 'trial_type'); - %% check header writing with extra columns - fprintf('\n\n--------------------------------------------------------------------'); +end - clear; +function test_saveEventsFileOpenExtraColumns() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up + %% set up + + cfg.verbose = false; cfg.subject.subjectNb = 1; + cfg.subject.runNb = 1; + cfg.task.name = 'testtask'; + cfg.dir.output = outputDir; cfg.testingDevice = 'mri'; - % define the extra columns: they will be added to the tsv files in the order the user input them - logFile.extraColumns = {'Speed', 'is_Fixation'}; - - %%% do stuff - cfg = createFilename(cfg); + % define the extra columns + % they will be added to the tsv files in the order the user input them + logFile.extraColumns = {'Speed', 'is_Fixation'}; + % create the events file and header logFile = saveEventsFile('open', cfg, logFile); % close the file saveEventsFile('close', cfg, logFile); - %%% test section + %% data to test against % open the file funcDir = fullfile(cfg.dir.outputSubject, cfg.fileName.modality); @@ -81,11 +90,12 @@ function test_saveEventsFileOpen() FID = fopen(fullfile(funcDir, eventFilename), 'r'); C = textscan(FID, repmat('%s', 1, nbExtraCol + 3), 'Delimiter', '\t', 'EndOfLine', '\n'); + %% test % check the extra columns of the header - assert(isequal(C{1}{1}, 'onset')); - assert(isequal(C{2}{1}, 'duration')); - assert(isequal(C{3}{1}, 'trial_type')); - assert(isequal(C{4}{1}, 'Speed')); - assert(isequal(C{5}{1}, 'is_Fixation')); + assertEqual(C{1}{1}, 'onset'); + assertEqual(C{2}{1}, 'duration'); + assertEqual(C{3}{1}, 'trial_type'); + assertEqual(C{4}{1}, 'Speed'); + assertEqual(C{5}{1}, 'is_Fixation'); end diff --git a/tests/test_saveEventsFileOpenMultiColumn.m b/tests/test_saveEventsFileOpenMultiColumn.m index 69b0dc5b..05e63f41 100644 --- a/tests/test_saveEventsFileOpenMultiColumn.m +++ b/tests/test_saveEventsFileOpenMultiColumn.m @@ -1,15 +1,24 @@ -function test_saveEventsFileOpenMultiColumn() +function test_suite = test_saveEventsFileOpenMultiColumn %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end - %% check header writing with several columns for one variable - clear; +function test_saveEventsFileOpenMultiColumnCheckHeader() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up + %% set up + + cfg.verbose = false; cfg.subject.subjectNb = 1; cfg.subject.runNb = 1; + cfg.task.name = 'testtask'; + cfg.dir.output = outputDir; cfg.testingDevice = 'mri'; @@ -22,18 +31,14 @@ function test_saveEventsFileOpenMultiColumn() logFile.extraColumns.LHL24.length = 12; % will set 12 columns with names LHL24-01, LHL24-02, ... logFile.extraColumns.is_Fixation = []; % will set 1 columns with name is_Fixation - %%% do stuff - % create the events file and header logFile = saveEventsFile('open', cfg, logFile); % close the file saveEventsFile('close', cfg, logFile); - %%% test section - - % check the extra columns of the header and some of the content funcDir = fullfile(cfg.dir.outputSubject, cfg.fileName.modality); + eventFilename = cfg.fileName.events; nbExtraCol = ... @@ -41,13 +46,14 @@ function test_saveEventsFileOpenMultiColumn() logFile(1).extraColumns.LHL24.length + ... logFile(1).extraColumns.is_Fixation.length; + %% test FID = fopen(fullfile(funcDir, eventFilename), 'r'); C = textscan(FID, repmat('%s', 1, nbExtraCol + 3), 'Delimiter', '\t', 'EndOfLine', '\n'); % check the extra columns of the header - assert(isequal(C{4}{1}, 'Speed')); - assert(isequal(C{5}{1}, 'LHL24_01')); - assert(isequal(C{16}{1}, 'LHL24_12')); - assert(isequal(C{17}{1}, 'is_Fixation')); + assertEqual(C{4}{1}, 'Speed'); + assertEqual(C{5}{1}, 'LHL24_01'); + assertEqual(C{16}{1}, 'LHL24_12'); + assertEqual(C{17}{1}, 'is_Fixation'); end diff --git a/tests/test_saveEventsFileSave.m b/tests/test_saveEventsFileSave.m index 9cc610c5..514aee75 100644 --- a/tests/test_saveEventsFileSave.m +++ b/tests/test_saveEventsFileSave.m @@ -1,15 +1,24 @@ -function test_saveEventsFileSave() +function test_suite = test_saveEventsFileSave %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end - %% write things in it - clear; +function test_saveEventsFileSaveBasic() outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output'); - %%% set up + %% set up + + cfg.verbose = false; cfg.subject.subjectNb = 1; cfg.subject.runNb = 1; + cfg.task.name = 'testtask'; + cfg.dir.output = outputDir; cfg.testingDevice = 'mri'; @@ -23,8 +32,6 @@ function test_saveEventsFileSave() % create the events file and header logFile = saveEventsFile('open', cfg, logFile); - %%% do stuff - % ROW 2: normal events : all info is there logFile(1, 1).onset = 2; logFile(end, 1).trial_type = 'motion_up'; @@ -73,7 +80,7 @@ function test_saveEventsFileSave() % close the file saveEventsFile('close', cfg, logFile); - %%% test section + %% test % check the extra columns of the header and some of the content nbExtraCol = ... @@ -82,34 +89,36 @@ function test_saveEventsFileSave() logFile(1).extraColumns.is_Fixation.length; funcDir = fullfile(cfg.dir.outputSubject, cfg.fileName.modality); + eventFilename = cfg.fileName.events; + FID = fopen(fullfile(funcDir, eventFilename), 'r'); C = textscan(FID, repmat('%s', 1, nbExtraCol + 3), 'Delimiter', '\t', 'EndOfLine', '\n'); % event 1/ ROW 2: check that values are entered correctly - assert(isequal(C{1}{2}, sprintf('%f', 2))); - assert(isequal(C{3}{2}, 'motion_up')); - assert(isequal(C{2}{2}, sprintf('%f', 3))); - assert(isequal(C{4}{2}, sprintf('%f', 2))); - assert(isequal(C{5}{2}, sprintf('%f', 1))); - assert(isequal(C{16}{2}, sprintf('%f', 12))); - assert(isequal(C{17}{2}, 'true')); + assertEqual(C{1}{2}, sprintf('%f', 2)); + assertEqual(C{3}{2}, 'motion_up'); + assertEqual(C{2}{2}, sprintf('%f', 3)); + assertEqual(C{4}{2}, sprintf('%f', 2)); + assertEqual(C{5}{2}, sprintf('%f', 1)); + assertEqual(C{16}{2}, sprintf('%f', 12)); + assertEqual(C{17}{2}, 'true'); % event 2 / ROW 3: missing info replaced by nans - assert(isequal(C{4}{3}, 'n/a')); - assert(isequal(C{5}{3}, 'n/a')); - assert(isequal(C{16}{3}, 'n/a')); - assert(isequal(C{17}{3}, 'false')); + assertEqual(C{4}{3}, 'n/a'); + assertEqual(C{5}{3}, 'n/a'); + assertEqual(C{16}{3}, 'n/a'); + assertEqual(C{17}{3}, 'false'); % event 3 / ROW 4: missing info (duration is missing and speed is empty) - assert(isequal(C{2}{4}, 'n/a')); - assert(isequal(C{4}{4}, 'n/a')); + assertEqual(C{2}{4}, 'n/a'); + assertEqual(C{4}{4}, 'n/a'); % event 4-5 / ROW 5-6: skip empty events - assert(~isequal(C{1}{5}, 'n/a')); + assertTrue(~isequal(C{1}{5}, 'n/a')); % check values entered properly - assert(isequal(C{15}{5}, 'n/a')); - assert(isequal(C{16}{5}, 'n/a')); + assertEqual(C{15}{5}, 'n/a'); + assertEqual(C{16}{5}, 'n/a'); end diff --git a/tests/test_setDefaultFields.m b/tests/test_setDefaultFields.m index b0aea0fc..39ca05d4 100644 --- a/tests/test_setDefaultFields.m +++ b/tests/test_setDefaultFields.m @@ -1,19 +1,31 @@ -function test_setDefaultFields() +function test_suite = test_setDefaultFields %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_setDefaultFieldsWrite() + %% set up structure = struct(); fieldsToSet.field = 1; structure = setDefaultFields(structure, fieldsToSet); + %% data to test against expectedStructure.field = 1; - assert(isequal(expectedStructure, structure)); + %% test + assertEqual(expectedStructure, structure); - fprintf('\n--------------------------------------------------------------------'); +end - clear; +function test_setDefaultFieldsNoOverwrite() + % set up structure.field.subfield_1 = 3; fieldsToSet.field.subfield_1 = 1; @@ -21,9 +33,11 @@ function test_setDefaultFields() structure = setDefaultFields(structure, fieldsToSet); + % data to test against expectedStructure.field.subfield_1 = 3; expectedStructure.field.subfield_2 = 1; + % test assert(isequal(expectedStructure, structure)); end