Code covered by the BSD License  

Highlights from
mlunit_2008a

image thumbnail
from mlunit_2008a by Christopher
A MATLAB unit test framework supporting new classdef files (r2008a)

TextTestRunner
classdef TextTestRunner < TestRunner
    % TEXTTESTRUNNER A text-only interface for running tests.
    %
    % This class is part of the mlunit_2008a testing framework.
    %
    % The "public" interface of the class is as follows:
    %
    % TextTestRunner([names])
    %   Constructor for the TextTestRunner.  The optional names parameter
    %   lets you set up the runner with an initial set of tests.  See
    %   addTests below for syntax of the names parameter.
    % 
    % addTests(obj, names)
    %   Adds tests to the list of tests to be run by the runner.  The names
    %   parameter can be a string or a cell array of strings.  Each string
    %   should be the name of a test case or test suite class, which must
    %   be in the current MATLAB path. Any test results are lost.
    % 
    % clearTests(obj)
    %   Removes any previously added tests and any associated results.
    % 
    % runTests(obj)
    %   Runs all tests.  A text progress bar is provided, but note that it
    %   will be completely munged if any of the code under test uses disp
    %   or fprintf to write out to the screen.  After the run, a summary of
    %   test results is displayed.
    % 
    % showReport(obj)
    %   Shows a summary of any existing test results.  This is useful, for
    %   instance, while fixing a set of broken tests; rather than rerunning
    %   all of the tests, you can use showReport() to display the summary
    %   of the most recent test run.
    % 
    

    properties
        progressCount;
        failFlag;
    end

    % "public" interface
    methods
        function self = TextTestRunner(names)
            if nargin < 1, names = {}; end
            if ~iscell(names)
                names = {names};
            end
            self.test = DynamicTestSuite(names);
            self.initialize();
        end

        function addTests(self, names)
            if ~iscell(names)
                names = {names};
            end

            for i = 1:length(names)
                self.test.add(names{i});
            end

            self.initialize();
        end

        function clearTests(self)
            self.test = DynamicTestSuite();
            self.initialize();
        end

        function runTests(self, names)
            if nargin == 2
                self.clearTests();
                self.addTests(names);
            end
            self.initialize();

            % setup for progress monitoring
            fprintf('\nRunning tests:\n');
            fprintf('%% complete: 0');
            for p = 1:9
                fprintf('---+');
            end
            fprintf('--100\n');
            fprintf('            |');
            self.progressCount = 0;
            self.failFlag = false;

            try
                self.testResult.runTests();
            catch ME
                fprintf('\n\nStopped on exception:\n\n');
                disp(ME.getReport());
            end

            self.showReport();
        end

        function showReport(self)
            tc = self.testResult.testCount;
            fc = self.testResult.failureCount;
            sc = self.testResult.successCount;
            runs = fc + sc;

            fprintf('\nTest results: %d/%d attempted, %d successful, %d failed.\n\n', runs, tc, sc, fc);
            if fc > 0
                uresp = input('Show individual failures (y/N)?  ', 's');
                fprintf('\n');
                if strncmpi(uresp, 'y', 1)
                    self.showFailures(self.testResult.children, 0);
                end
            end
        end
    end

    % "private" methods
    methods
        function initialize(self)
            initialize@TestRunner(self);
            self.testResult.parent = self;
        end

        function incrementFailureCount(self)
            self.failFlag = true;
            self.updateProgress();
        end

        function incrementSuccessCount(self)
            self.updateProgress();
        end

        function updateProgress(self)
            tc = self.testResult.testCount;
            fc = self.testResult.failureCount;
            sc = self.testResult.successCount;
            runs = fc + sc;

            ticks = floor(40 * runs / tc);
            
            if ticks > self.progressCount
                c = '=';
                if self.failFlag
                    c = 'x';
                end
                while self.progressCount < ticks
                    fprintf(c);
                    self.progressCount = self.progressCount + 1;
                end
                self.failFlag = false;
            end
            
            if runs == tc
                fprintf('|\n');
            end
        end
        
        function showFailures(self, tresults, level)
            rnames = fieldnames(tresults);
            for i = 1:length(rnames)
                rn = rnames{i};
                tr = tresults.(rn);
                if tr.failureCount > 0
                    self.printBlanks(level);
                    fprintf('%s\n', rn);
                    
                    if tr.isSuite();
                        self.showFailures(tr.children, level+1);
                    else
                        self.showMethodFailures(tr.children, level+1);
                    end
                end
            end
            fprintf('\n');
        end
        
        function showMethodFailures(self, mresults, level)
            mnames = fieldnames(mresults);
            for i = 1:length(mnames)
                mn = mnames{i};
                mr = mresults.(mn);
                if isstruct(mr)
                    self.printBlanks(level);
                    fprintf('%s: %s\n', mn, mr.message);
                end
            end
        end
        
        function printBlanks(self, count)
            for i = 1:count
                fprintf('  ');
            end
        end
        
        function display(self)
            fprintf('a TextTestRunner ');
            if isempty(self.test) || isempty(self.test.children)
                fprintf('(no tests)');
            elseif isempty(self.testResult) || (self.testResult.failureCount + self.testResult.successCount) == 0
                fprintf('(no results)');
            else
                tc = self.testResult.testCount;
                fc = self.testResult.failureCount;
                sc = self.testResult.successCount;
                runs = fc + sc;

                fprintf('(%d/%d results, %d successful, %d failed)', runs, tc, sc, fc);
            end
            fprintf('\n');
        end

            
    end
end

Contact us at files@mathworks.com