diff --git a/matlab/run_gdat_tests.m b/matlab/run_gdat_tests.m
index 94191dbbded2815289f32c2e9c8872dab825ea84..5f3f8b0747f17646a5616ee60821c1cc347585c5 100644
--- a/matlab/run_gdat_tests.m
+++ b/matlab/run_gdat_tests.m
@@ -1,39 +1,61 @@
-function [passed,results] = run_gdat_tests(test_case)
-% test runner for gdat
-
-% F. Felici, EPFL federico.felici@epfl.ch
+function [passed,results] = run_tbx_tests(test_case)
+% Test runner for generic toolbox tests
 
 if nargin==0 || isempty(test_case)
-  test_case = 'basic-tcv'; % default
+  test_case = 'basic'; % default
+end
+
+if nargin < 2
+  coverage_report = false; % default
 end
-test_case = lower(test_case);
+
+assert(~(coverage_report && strcmpi(test_case,'coverage')),'coverage_report=true should only be used with test_case=''coverage''');
+
+needXML=~isempty(getenv('GITLAB_CI')) && ~verLessThan('matlab','8.6.0');
+needCOV=~isempty(getenv('GITLAB_CI')) && ~verLessThan('matlab','9.6.0') || coverage_report;
+
+%% Default outputs
+passed=false; results=[]; % default outputs
 
 %% Import some classes we need
 import matlab.unittest.selectors.HasTag;
 import matlab.unittest.constraints.ContainsSubstring;
 import matlab.unittest.selectors.HasName;
+if needXML
+  import matlab.unittest.plugins.XMLPlugin;
+end
 
-%% populate suite
-% add path with tests
-addpath(genpath(fullfile(fileparts(mfilename('fullpath')),'tests')));
-addpath(genpath(fullfile(fileparts(mfilename('fullpath')),'TCV_IMAS')));
+%% Paths
+% add path of toolbox to make sure it is in the path
+tbxpath = fileparts(mfilename('fullpath'));
+addpath(tbxpath); % add default path
 
-% aug cannot be tested without a tunnel created
-% $$$ suite_all = [matlab.unittest.TestSuite.fromClass(?test_requestnames_tcv),...
-% $$$   matlab.unittest.TestSuite.fromClass(?test_requestnames_aug),...
-% $$$   matlab.unittest.TestSuite.fromClass(?test_tcv_get_ids)];
+% add additional paths present in a local setpaths_* file
+setpathsfile = dir(fullfile(tbxpath,'setpaths_*'));
+if numel(setpathsfile)==1
+  fname = fullfile(tbxpath,setpathsfile.name);
+  fprintf('adding extra paths by calling %s\n',fname);
+  run(fname); % run file to add paths
+elseif numel(setpathsfile)>1
+  error('multiple setpaths_* files found!');
+end
 
-suite_all = [matlab.unittest.TestSuite.fromClass(?test_requestnames_tcv),...
-  matlab.unittest.TestSuite.fromClass(?test_tcv_get_ids)];
+%% Generate test suite
+testspath = fullfile(tbxpath,'tests');
 
-switch test_case
+lastwarn('','');
+suite_all = matlab.unittest.TestSuite.fromFolder(testspath);
+[~,s] = lastwarn();
+if isequal(s,'MATLAB:unittest:TestSuite:FileExcluded')
+  fprintf('File excluded during test suite creation - possible syntax errors in a test class');
+  return
+end
+ 
+switch lower(test_case)
   case 'all'
     suite = suite_all; % run all
-  case 'basic-tcv'
-    s = ~HasTag('slow') & HasName(ContainsSubstring('tcv'));
-    suite = suite_all.selectIf(s);
-  case 'imas'
-    s = HasTag('imas');
+  case 'basic'
+    s = ~HasTag('slow');
     suite = suite_all.selectIf(s);
   case 'tcv'
     s = HasName(ContainsSubstring('tcv'));
@@ -41,30 +63,59 @@ switch test_case
   case 'aug'
     s = HasName(ContainsSubstring('aug'));
     suite = suite_all.selectIf(s);
-
   otherwise
-    error('unknown test_case %s',test_case)
+    s = HasTag(test_case);
+    suite = suite_all.selectIf(s);
+end
+
+if isempty(suite)
+  fprintf('\nEmpty test suite returned for TestTag=''%s''\n',test_case); return;
 end
 
 %% run it
 fprintf('Start test case: %s\n%s\n\n',test_case,datestr(now));
-results = run(suite);
+runner = matlab.unittest.TestRunner.withTextOutput;
+if needXML
+  % Add some JUnit XML file with tests results
+  xmlFile = fullfile(getenv('CI_PROJECT_DIR'),sprintf('test_%s_%s.xml',test_case,version('-release')));
+  fprintf('\tGenerating JUnit XML report at %s\n',xmlFile);
+  p = XMLPlugin.producingJUnitFormat(xmlFile);
+  runner.addPlugin(p)
+end
+if needCOV
+  % Add some code coverage report
+  switch lower(test_case)
+    case 'coverage'
+      % Produce HTML report
+      reportFolder = sprintf('test_%s_cov',version('-release'));
+      reportFormat = matlab.unittest.plugins.codecoverage.CoverageReport(reportFolder);
+    otherwise
+      % Produce XML file in Cobertura format (for Gitlab MR viz.)
+      xmlFile = sprintf('test_%s_%s_cov.xml',test_case,version('-release'));
+      reportFormat = matlab.unittest.plugins.codecoverage.CoberturaFormat(xmlFile);
+  end
+  p = matlab.unittest.plugins.CodeCoveragePlugin.forFolder(fileparts(mfilename('fullpath')),...
+    'IncludingSubfolders',true,'Producing',reportFormat);
+  runner.addPlugin(p)
+end
+results = runner.run(suite);
 disp(table(results));
 fprintf('\nTotal test duration: %5.2fs\n',sum(table(results).Duration))
 
-%% display results
 if all([results.Passed])
   fprintf('\nPassed all tests\n')
   passed = true;
-else
-  fprintf('\nSome tests Failed or Incomplete\n')
-  if any([results.Incomplete])
-    fprintf('\nIncomplete:\n')
-    disp(table(results([results.Incomplete])))
-  end
-  if any([results.Failed])
-    fprintf('\nFailed:\n')
-    disp(table(results([results.Failed])));
-  end
+elseif any([results.Failed])
+  fprintf('\nSome tests Failed\n')
+  disp(table(results([results.Failed])))
   passed = false;
+elseif any([results.Incomplete])
+  fprintf('\nSome tests Incomplete\n')
+  disp(table(results([results.Incomplete])));
+  passed = true; % pass tests even if some were skipped
+else
+  % the conditions above should cover all cases, otherwise 
+  error('something is very wrong - please check')
+end
+
 end