Skip to main content
Engineering LibreTexts

9.6: The SUnit Framework

  • Page ID
    39624
    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    SUnit consists of four main classes: TestCase, TestSuite, TestResult, and TestResource, as shown in Figure \(\PageIndex{1}\). The notion of a test resource represents a resource that is expensive to set-up but which can be used by a whole series of tests. A TestResource specifies a setUp method that is executed just once before a suite of tests; this is in distinction to the TestCase >> setUp method, which is executed before each test.

    The four classes representing the core of SUnit.
    Figure \(\PageIndex{1}\): The four classes representing the core of SUnit.

    TestCase

    TestCase is an abstract class that is designed to be subclassed. Each of its subclasses represents a group of tests that share a common context (that is, a test suite). Each test is run by creating a new instance of a subclass of TestCase, running setUp, running the test method itself, and then sending the tearDown.

    The context is specified by instance variables of the subclass and by the specialization of the method setUp, which initializes those instance variables. Subclasses of TestCase can also override method tearDown, which is invoked after the execution of each test, and can be used to release any objects allocated during setUp.

    TestSuite

    Instances of the class TestSuite contain a collection of test cases. An instance of TestSuite contains tests, and other test suites. That is, a test suite contains sub-instances of TestCase and TestSuite.

    Both individual test cases and test suites understand the same protocol, so they can be treated in the same way (for example, both can be run). This is in fact an application of the Composite pattern in which TestSuite is the composite and the test cases are the leaves.

    TestResult

    The class TestResult represents the results of a TestSuite execution. It records the number of tests passed, the number of tests failed, and the number of errors signalled.

    TestResource

    One of the important features of a suite of tests is that they should be independent of each other. The failure of one test should not cause an avalanche of failures of other tests that depend upon it, nor should the order in which the tests are run matter. Performing setUp before each test and tearDown afterwards helps to reinforce this independence.

    However, there are occasions where setting up the necessary context is just too time-consuming for it to be done before the execution of each test. Moreover, if it is known that the test cases do not disrupt the resources used by the tests, then it is wasteful to set them up afresh for each test. It is sufficient to set them up once for each suite of tests. Suppose, for example, that a suite of tests needs to query a database, or do analysis on some compiled code. In such cases, it may make sense to set up the database and open a connection to it, or to compile some source code, before any of the tests start to run.

    Where should we cache these resources, so that they can be shared by a suite of tests? The instance variables of a particular TestCase subclass won’t do, because a TestCase instance persists only for the duration of a single test (as mentioned before, the instance is created anew for each test method). A global variable would work, but using too many global variables pollutes the name space, and the binding between the global and the tests that depend on it will not be explicit. A better solution is to put the necessary resources in a singleton object of some class. The class TestResource exists to be subclassed by such resource classes. Each subclass of TestResource understands the message current, which will answer a singleton instance of that subclass. Methods setUp and tearDown should be overridden in the subclass to ensure that the resource is initialized and finalized.

    One thing remains: somehow, SUnit has to be told which resources are associ- ated with which test suite. A resource is associated with a particular subclass of TestCase by overriding the class method resources.

    By default, the resources of a TestSuite are the union of the resources of the TestCases that it contains.

    Here is an example. We define a subclass of TestResource called MyTestResource. Then we associate it with MyTestCase by overriding the class method MyTestCase class >> resources to return an array of the test resource classes that MyTestCase will use.

    TestResource subclass: #MyTestResource
        instanceVariableNames: ''
        ...
    
    MyTestCase class >> resources
       "Associate the resource with this class of test cases"
    
       ^ { MyTestResource }
    

    Exercise

    The following trace (written to the Transcript) illustrates that a global set up is run before and after each test in a sequence. Let’s see if you can obtain this trace yourself.

    MyTestResource >> setUp has run.
    MyTestCase >> setUp has run.
    MyTestCase >> testOne has run.
    MyTestCase >> tearDown has run.
    MyTestCase >> setUp has run.
    MyTestCase >> testTwo has run.
    MyTestCase >> tearDown has run.
    MyTestResource >> tearDown has run.
    

    Create new classes MyTestResource and MyTestCase which are subclasses of TestResource and TestCase respectively. Add the appropriate methods so that the following messages are written to the Transcript when you run your tests.

    Solution.

    You will need to write the following six methods.

    MyTestCase >> setUp
        Transcript show: 'MyTestCase>>setUp has run.'; cr
    
    MyTestCase >> tearDown
        Transcript show: 'MyTestCase>>tearDown has run.'; cr
    
    MyTestCase >> testOne
        Transcript show: 'MyTestCase>>testOne has run.'; cr
    
    MyTestCase >> testTwo
        Transcript show: 'MyTestCase>>testTwo has run.'; cr
    
    MyTestCase class >> resources
        ^ Array with: MyTestResource
    
    MyTestResource >> setUp
        Transcript show: 'MyTestResource>>setUp has run'; cr
    
    MyTestResource >> tearDown
        Transcript show: 'MyTestResource>>tearDown has run.'; cr
    

    This page titled 9.6: The SUnit Framework is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.