From 644c538c60b6a7622f94b1f9bc07b5c43fea698a Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Thu, 29 Mar 2012 15:10:59 -0700 Subject: [PATCH 1/9] Added .gitignore for *.asv files --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e3461a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.asv From 86fb63f9da665350f205b38173315a768da3c01f Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Thu, 29 Mar 2012 15:11:48 -0700 Subject: [PATCH 2/9] Made multiple loggings possible. Maybe I want xml, logfile and console output --- xunit/MetaTestRunLogger.m | 45 +++++++++++++++++++++++++++++ xunit/runtests.m | 61 +++++++++++++++++++++++++-------------- 2 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 xunit/MetaTestRunLogger.m diff --git a/xunit/MetaTestRunLogger.m b/xunit/MetaTestRunLogger.m new file mode 100644 index 0000000..230e8dd --- /dev/null +++ b/xunit/MetaTestRunLogger.m @@ -0,0 +1,45 @@ +classdef MetaTestRunLogger + %METATESTRUNLOGGER Combine several test run loggers into one + % Implement the 4 methods of a matlab-xunit test logger on each of + % a cell array of instantiated input loggers. + + properties + loggers = {}; + end + + methods + function self = MetaTestRunLogger(loggers) + self.loggers = loggers; + end + + function testComponentStarted(self, component) + for ii=1:length(self.loggers) + logger = self.loggers{ii}{1}; + logger.testComponentStarted(component); + end + end + + function testComponentFinished(self, component, did_pass) + for ii=1:length(self.loggers) + logger = self.loggers{ii}{1}; + logger.testComponentFinished(component, did_pass); + end + end + + function testCaseFailure(self, test_case, failure_exception) + for ii=1:length(self.loggers) + logger = self.loggers{ii}{1}; + logger.testCaseFailure(test_case, failure_exception); + end + end + + function testCaseError(self, test_case, error_exception) + for ii=1:length(self.loggers) + logger = self.loggers{ii}{1}; + logger.testCaseError(test_case, error_exception); + end + end + end + +end + diff --git a/xunit/runtests.m b/xunit/runtests.m index 1ef6d5b..bdf49ec 100644 --- a/xunit/runtests.m +++ b/xunit/runtests.m @@ -85,11 +85,12 @@ verbose = false; logfile = ''; -isxml = false; +xmlfile = ''; +suppress = false; if nargin < 1 suite = TestSuite.fromPwd(); else - [name_list, verbose, logfile, isxml] = getInputNames(varargin{:}); + [name_list, verbose, logfile, xmlfile, suppress] = getInputNames(varargin{:}); if numel(name_list) == 0 suite = TestSuite.fromPwd(); elseif numel(name_list) == 1 @@ -106,17 +107,33 @@ error('xunit:runtests:noTestCasesFound', 'No test cases found.'); end -if ~ isxml - if isempty(logfile) - logfile_handle = 1; % File handle corresponding to Command Window +if(suppress && isempty(logfile) && isempty(xmlfile)) + error('xunit:runtests:noOutputFound', 'You should specify at least one way to get your test results.'); +end + +loggers = {}; + +if ~suppress % Display output to command line + if verbose + loggers{end+1} = {VerboseTestRunDisplay(1)}; else - logfile_handle = fopen(logfile, 'w'); - if logfile_handle < 0 - error('xunit:runtests:FileOpenFailed', ... - 'Could not open "%s" for writing.', logfile); - else - cleanup = onCleanup(@() fclose(logfile_handle)); - end + loggers{end+1} = {TestRunDisplay(1)}; + end +end + +if ~isempty(logfile) % Log output to a log file. + logfile_handle = fopen(logfile, 'w'); + if logfile_handle < 0 + error('xunit:runtests:FileOpenFailed', ... + 'Could not open "%s" for writing.', logfile); + else + cleanup = onCleanup(@() fclose(logfile_handle)); + end + + if verbose + loggers{end+1} = {VerboseTestRunDisplay(logfile_handle)}; + else + loggers{end+1} = {TestRunDisplay(logfile_handle)}; end fprintf(logfile_handle, 'Test suite: %s\n', suite.Name); @@ -126,24 +143,23 @@ fprintf(logfile_handle, '%s\n\n', datestr(now)); end -if isxml - monitor = XMLTestRunLogger(logfile); -elseif verbose - monitor = VerboseTestRunDisplay(logfile_handle); -else - monitor = TestRunDisplay(logfile_handle); +if isempty(xmlfile) % Create an xml file. + loggers{end+1} = {XMLTestRunLogger(xmlfile)}; end + +monitor = MetaTestRunLogger(loggers); did_pass = suite.run(monitor); if nargout > 0 out = did_pass; end -function [name_list, verbose, logfile, isxml] = getInputNames(varargin) +function [name_list, verbose, logfile, xmlfile, suppress] = getInputNames(varargin) name_list = {}; verbose = false; logfile = ''; -isxml = false; +xmlfile = ''; +suppress = false; k = 1; while k <= numel(varargin) arg = varargin{k}; @@ -152,6 +168,8 @@ elseif ~isempty(arg) && (arg(1) == '-') if strcmp(arg, '-verbose') verbose = true; + elseif strcmp(arg, '-suppress') + suppress = true; elseif strcmp(arg, '-logfile') if k == numel(varargin) error('xunit:runtests:MissingLogfile', ... @@ -165,8 +183,7 @@ error('xunit:runtests:MissingXMLfile', ... 'The option -xmlfile must be followed by a filename.'); else - isxml = true; - logfile = varargin{k+1}; + xmlfile = varargin{k+1}; k = k + 1; end else From cd9a9a3de1fb4d5be66d36fb4a98703f73d9e778 Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Fri, 30 Mar 2012 11:23:11 -0700 Subject: [PATCH 3/9] Enhanced xml output to do separate files under the right conditions. --- xunit/MetaTestRunLogger.m | 4 ++-- xunit/XMLTestRunLogger.m | 33 +++++++++++++++++++++++++++++---- xunit/runtests.m | 6 +++++- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/xunit/MetaTestRunLogger.m b/xunit/MetaTestRunLogger.m index 230e8dd..e75df6b 100644 --- a/xunit/MetaTestRunLogger.m +++ b/xunit/MetaTestRunLogger.m @@ -1,4 +1,4 @@ -classdef MetaTestRunLogger +classdef MetaTestRunLogger < TestRunMonitor %METATESTRUNLOGGER Combine several test run loggers into one % Implement the 4 methods of a matlab-xunit test logger on each of % a cell array of instantiated input loggers. @@ -38,7 +38,7 @@ function testCaseError(self, test_case, error_exception) logger = self.loggers{ii}{1}; logger.testCaseError(test_case, error_exception); end - end + end end end diff --git a/xunit/XMLTestRunLogger.m b/xunit/XMLTestRunLogger.m index c9ba5e9..492292c 100644 --- a/xunit/XMLTestRunLogger.m +++ b/xunit/XMLTestRunLogger.m @@ -44,8 +44,9 @@ function testComponentStarted(self, component) self.TCNum = self.TCNum + 1; self.Results.testcase{self.TCNum}.ATTRIBUTE.classname = self.CurrentClass; self.Results.testcase{end}.ATTRIBUTE.name = component.Name; - else - self.CurrentClass = component.Name; + elseif isa(component, 'TestSuite') + self.testSuiteFinished() + self.CurrentClass = component.Name; end end @@ -90,7 +91,7 @@ function testCaseError(self, test_case, error_exception) end methods (Access = protected) - function testRunFinished(self) + function writeResults(self, filename) self.Results.ATTRIBUTE.tests = self.TCNum; self.Results.ATTRIBUTE.skip = 0; self.Results.ATTRIBUTE.failures = self.FailureNum; @@ -99,11 +100,35 @@ function testRunFinished(self) wPref.StructItem = false; wPref.CellItem = false; - xml_write(self.ReportFile, self.Results, 'testsuite', wPref); + xml_write(filename, self.Results, 'testsuite', wPref); + end + + % ONLY IF the ReportFile is a directory, write an xml file for each + % suite. + function testSuiteFinished(self) + [~, filename] = fileparts(self.ReportFile); + if isempty(filename) && ~isempty(self.CurrentClass) + self.Results.ATTRIBUTE.name = self.CurrentClass; + self.writeResults(self.getResultFileName()); + + self.Results = struct; + self.TCNum = 0; + end + end + + function testRunFinished(self) + self.writeResults(self.getResultFileName()); end end methods (Access = private) + function filename = getResultFileName(self) + [pathname, filename] = fileparts(self.ReportFile); + if isempty(filename) + filename = fullfile(pathname, ['TEST-' self.CurrentClass '.xml']); + end + end + function pushTic(self) self.TicStack(end+1) = tic; end diff --git a/xunit/runtests.m b/xunit/runtests.m index bdf49ec..1e61579 100644 --- a/xunit/runtests.m +++ b/xunit/runtests.m @@ -41,6 +41,10 @@ % Window. This format is compatible with JUnit, and can be read by many % tools. % +% You can also pass a directory path instead of a file path to +% '-xmlfile'. If you do this, an xml file will be created for each suite, +% which Jenkins will be able to present more helpfully. +% % out = runtests(...) returns a logical value that is true if all the % tests passed. % @@ -143,7 +147,7 @@ fprintf(logfile_handle, '%s\n\n', datestr(now)); end -if isempty(xmlfile) % Create an xml file. +if ~isempty(xmlfile) % Create an xml file. loggers{end+1} = {XMLTestRunLogger(xmlfile)}; end From bd43b7b2ca333284ec2d983c5aeda9cb35e98448 Mon Sep 17 00:00:00 2001 From: blueacorn Date: Wed, 1 Jun 2016 08:28:06 -0700 Subject: [PATCH 4/9] Moved MetaTestRunLogger.m to src\ path --- {xunit => src}/MetaTestRunLogger.m | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {xunit => src}/MetaTestRunLogger.m (100%) diff --git a/xunit/MetaTestRunLogger.m b/src/MetaTestRunLogger.m similarity index 100% rename from xunit/MetaTestRunLogger.m rename to src/MetaTestRunLogger.m From e5f95fb3785c438bcaaa743cd2cf421f03d3cd47 Mon Sep 17 00:00:00 2001 From: blueacorn Date: Wed, 1 Jun 2016 08:58:14 -0700 Subject: [PATCH 5/9] Updated runxunit.m help text for multiple output logger options. --- src/runxunit.m | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/runxunit.m b/src/runxunit.m index c72518c..eb1a620 100644 --- a/src/runxunit.m +++ b/src/runxunit.m @@ -1,7 +1,7 @@ function out = runxunit(varargin) %runxunit Run unit tests -% runxunit runs all the test cases that can be found in the current directory -% and summarizes the results in the Command Window. +% runxunit runs all the test cases that can be found in the current +% directory and summarizes the results in the Command Window. % % Test cases can be found in the following places in the current directory: % @@ -19,27 +19,29 @@ % runxunit(packagename) runs all the test cases found in the specified % package. (This option requires R2009a or later). % -% runxunit(mfilename) runs test cases found in the specified function or class -% name. The function or class needs to be in the current directory or on the -% MATLAB path. +% runxunit(mfilename) runs test cases found in the specified function or +% class name. The function or class needs to be in the current directory +% or on the MATLAB path. % -% runxunit('mfilename:testname') runs the specific test case named 'testname' -% found in the function or class 'name'. +% runxunit('mfilename:testname') runs the specific test case named +% 'testname' found in the function or class 'name'. % % Multiple directories or file names can be specified by passing multiple % names to runxunit, as in runxunit(name1, name2, ...) or % runxunit({name1, name2, ...}, ...) % -% runxunit(..., '-verbose') displays the name and result, result, and time -% taken for each test case to the Command Window. +% runxunit(..., '-verbose') displays the name, result, and time taken for +% each test case to the Command Window. % % runxunit(..., '-logfile', filename) directs the output of runxunit to -% the specified log file instead of to the Command Window. +% the specified log. % % runxunit(..., '-xmlfile', filename) directs the output of runxunit to -% the specified xUnit-formatted XML log file instead of to the Command -% Window. This format is compatible with JUnit, and can be read by many -% tools. +% the specified xUnit-formatted XML log file. This format is compatible +% with JUnit, and can be read by many tools. +% +% runxunit(..., '-suppress') suppresses output of runxunit to the Command +% Window. % % You can also pass a directory path instead of a file path to % '-xmlfile'. If you do this, an xml file will be created for each suite, From 1fd32711a3a06777ac9f9170b1991390f68ca698 Mon Sep 17 00:00:00 2001 From: blueacorn Date: Wed, 1 Jun 2016 08:59:05 -0700 Subject: [PATCH 6/9] Add narginchk.m for compatibility with Matlab version < R2011b - From https://gist.github.com/hagenw/5642886 --- src/narginchk.m | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/narginchk.m diff --git a/src/narginchk.m b/src/narginchk.m new file mode 100644 index 0000000..1ca116a --- /dev/null +++ b/src/narginchk.m @@ -0,0 +1,23 @@ +function narginchk(minargs, maxargs) + + if (nargin ~= 2) + error('%s: Usage: narginchk(minargs, maxargs)',upper(mfilename)); + elseif (~isnumeric (minargs) || ~isscalar (minargs)) + error ('minargs must be a numeric scalar'); + elseif (~isnumeric (maxargs) || ~isscalar (maxargs)) + error ('maxargs must be a numeric scalar'); + elseif (minargs > maxargs) + error ('minargs cannot be larger than maxargs') + end + + + args = evalin ('caller', 'nargin;'); + + + if (args < minargs) + error ('MATLAB:narginchk:notEnoughInputs', 'not enough input arguments'); + elseif (args > maxargs) + error ('MATLAB:narginchk:tooManyInputs', 'too many input arguments'); + end + +end \ No newline at end of file From 746ba0a255e6ead4b2477150dbc64e15f4ce8393 Mon Sep 17 00:00:00 2001 From: blueacorn Date: Wed, 1 Jun 2016 09:01:00 -0700 Subject: [PATCH 7/9] Fixed narginchk.m formatting to match Matlab R2011b version - From: http://www.mathworks.com/help/matlab/ref/narginchk.html --- src/narginchk.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/narginchk.m b/src/narginchk.m index 1ca116a..b9dcea5 100644 --- a/src/narginchk.m +++ b/src/narginchk.m @@ -15,9 +15,9 @@ function narginchk(minargs, maxargs) if (args < minargs) - error ('MATLAB:narginchk:notEnoughInputs', 'not enough input arguments'); + error ('MATLAB:narginchk:notEnoughInputs', 'Not enough input arguments.'); elseif (args > maxargs) - error ('MATLAB:narginchk:tooManyInputs', 'too many input arguments'); + error ('MATLAB:narginchk:tooManyInputs', 'Too many input arguments.'); end end \ No newline at end of file From e93ee2ac1089f60630735380a84ff3bd23a059a1 Mon Sep 17 00:00:00 2001 From: blueacorn Date: Wed, 1 Jun 2016 09:19:36 -0700 Subject: [PATCH 8/9] BugFix: Edited XMLTestRunLogger.m to pass XML write tests - function filename = getResultFileName(self) added else clause to return full xml filename --- src/XMLTestRunLogger.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/XMLTestRunLogger.m b/src/XMLTestRunLogger.m index 6e1c1c1..d764081 100644 --- a/src/XMLTestRunLogger.m +++ b/src/XMLTestRunLogger.m @@ -53,7 +53,7 @@ function testComponentStarted(self, component) self.Results.testcase{end}.ATTRIBUTE.name = component.Name; elseif isa(component, 'TestSuite') self.testSuiteFinished() - self.CurrentClass = component.Name; + self.CurrentClass = component.Name; end end @@ -119,7 +119,7 @@ function writeResults(self, filename) function testSuiteFinished(self) [~, filename] = fileparts(self.ReportFile); if isempty(filename) && ~isempty(self.CurrentClass) - self.Results.ATTRIBUTE.name = self.CurrentClass; + self.Results.ATTRIBUTE.name = self.CurrentClass; self.writeResults(self.getResultFileName()); self.Results = struct; @@ -141,6 +141,8 @@ function testRunFinished(self) [pathname, filename] = fileparts(self.ReportFile); if isempty(filename) filename = fullfile(pathname, ['TEST-' self.CurrentClass '.xml']); + else + filename = self.ReportFile; end end From 44a1e31e26ef387ce281f9953b954ad1443390ee Mon Sep 17 00:00:00 2001 From: blueacorn Date: Wed, 1 Jun 2016 09:37:35 -0700 Subject: [PATCH 9/9] Minor correction to runxunit.m help, to specify -xmlfile directory path should be absolute --- src/runxunit.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runxunit.m b/src/runxunit.m index eb1a620..30fb81b 100644 --- a/src/runxunit.m +++ b/src/runxunit.m @@ -40,13 +40,13 @@ % the specified xUnit-formatted XML log file. This format is compatible % with JUnit, and can be read by many tools. % -% runxunit(..., '-suppress') suppresses output of runxunit to the Command -% Window. -% -% You can also pass a directory path instead of a file path to +% You can also pass an absolute directory path instead of a file path to % '-xmlfile'. If you do this, an xml file will be created for each suite, % which Jenkins will be able to present more helpfully. % +% runxunit(..., '-suppress') suppresses output of runxunit to the Command +% Window. +% % out = runxunit(...) returns a logical value that is true if all the % tests passed. %