Consider a process composed of three algorithms: makeRuns, meld and traverse (each taking the output of the previous one as input): it is interesting to test each separately. Now consider three (or more) instances (e.g. singleton, twoPairs, SimplePair): it is interesting to test the behavior of the three algorithms on each of those instances. The result can be described as an array of (say) 3*3 tests. Is the code below the correct implementation of such a test? (I find the result of the tests to be lacking in clarity.)import unittest, doctestimport insertionRank##############################################################################class TestMTDRAG(unittest.TestCase):    def test_singleton(self):        Basic example [1].        run = makeRuns([1])        self.assertEqual(run,[Node(1,1)])        graph = meld(run)        self.assertEqual(graph,Node(1,1))        lengths=traverse(graph)        self.assertEqual(lengths,[1,0])    def test_TwoPairsExample(self):        Two messages of distinct probabilities [1,2].        run = makeRuns([1,2])        self.assertEqual(run,[Node(1,1),Node(2,1)])        graph = meld(run)        self.assertEqual(graph,Node(3,1,[Node(1,1),Node(2,1)]))        lengths=traverse(graph)        self.assertEqual(lengths,[0,2,0])    def test_SimplePairExample(self):        Basic example of four equiprobable messages [1,1,1,1].        run = makeRuns([1,1,1,1])        self.assertEqual(run,[Node(1,4)])        graph = meld(run)        self.assertEqual(graph,                         Node(4,1,                              [Node(2,2,[Node(1,4),Node(1,4)]),                               Node(2,2,[Node(1,4),Node(1,4)])                               ]))        lengths=traverse(graph)        self.assertEqual(lengths,[0,0,4])##############################################################################class Node(object):        A node in a MTDRAG (Moffat-Turpin Directed Rooted Acyclic Graph).        def __init__(self, weight, frequency, children=[], minDepth=None, nbPathsAtMinDepth=0, nbPathsAtMinDepthPlusOne=0):        assert frequency>0        self.weight = weight        self.frequency = frequency        self.children = children        self.minDepth= minDepth        self.nbPathsAtMinDepth = nbPathsAtMinDepth        self.nbPathsAtMinDepthPlusOne = nbPathsAtMinDepthPlusOne    def computeDepths(self,depthParent=-1,nd=1,ndp1=0):        assert self.frequency>0        if self.minDepth==None: # Node is not yet labeled            self.minDepth = depthParent+1            self.nbPathsAtMinDepth = nd            self.nbPathsAtMinDepthPlusOne = ndp1        elif self.minDepth == depthParent: # Node labeled at same depth as parent            self.nbPathsAtMinDepthPlusOne += nd        else:            assert(self.minDepth==depthParent+1) # Node labeled at depth + 1 of parent            self.nbPathsAtMinDepth += nd            self.nbPathsAtMinDepthPlusOne += ndp1        if self.nbPathsAtMinDepthPlusOne > 0:            maxDepth = depthParent+2        else:            maxDepth = depthParent+1        for child in self.children:            maxDepth = max( maxDepth,                            child.computeDepths(depthParent+1,self.nbPathsAtMinDepth,self.nbPathsAtMinDepthPlusOne)                            )        return maxDepth    def collectDepths(self,M):        assert self.frequency>0        if self.children == []:             M[self.minDepth] += self.nbPathsAtMinDepth            M[self.minDepth+1] += self.nbPathsAtMinDepthPlusOne        else:            for child in self.children:                child.collectDepths(M)    def __eq__(self,node):        assert self.frequency>0        if node == None:            return False        assert node.frequency>0        return self.weight==node.weight and self.frequency == node.frequency and self.children == node.children    def __str__(self):        assert self.frequency>0        if self.children == None:            return (+str(self.weight)+, +str(self.frequency)+)        else:            return (+str(self.weight)+, +str(self.frequency)+, +str(self.children)+)    def __repr__(self):        assert self.frequency>0        return self.__str__()    def copy(self):        assert self.frequency>0        return Node(self.weight,self.frequency,self.children,self.minDepth,self.nbPathsAtMinDepth,self.nbPathsAtMinDepthPlusOne)##############################################################################def makeRuns(A):    Compresses a list of INTEGER weights into a list of nodes, in    sublinear time (if all weights are not distinct).         A.sort() # Linear if already sorted    output = []    position = 0    while position < len(A):        weight = A[position]        frequency = insertionRank.fibonacciSearch(A[position:],weight+1)        output.append(Node(weight,frequency))        position += frequency    return outputdef meld(leaves):    Moffat and Turpin's algorithm to simulate van Leeuwen's    algorithm on a compressed representation of a list of weights.        assert(len(leaves)>0)    graphs = []    source = leaves    first = source[0]    while first.frequency>1 or len(leaves)+len(graphs)>=2:        if first.frequency>1:            graphs.append(Node(first.weight*2,first.frequency//2,[first,first]))            if first.frequency %2 == 1:                first.frequency = 1            else:                source.remove(first)        else: #first.frequency == 1 but len(leaves)+len(graphs)>=2            source.remove(first)            source = min(s for s in (leaves,graphs) if s)            second = source[0]            assert(second.frequency>0)            if second.frequency==1:                source.remove(second)                graphs.append(Node(first.weight+second.weight,1,[first,second]))            else:                extract = second.copy()                extract.frequency=1                second.frequency -= 1                graphs.append(Node(first.weight+extract.weight,1,[first,extract]))        source = min(s for s in (leaves,graphs) if s)        first = source[0]    return(first)def traverse(graph):    Computes an array containing the depth of the leaves of the    graph produced by the algorithm meld().         if graph==None:         return None    maxDepth = graph.computeDepths()    M = [0]*(maxDepth+2)    graph.collectDepths(M)    return M##############################################################################def main():    unittest.main()if __name__ == '__main__':    doctest.testmod()    main()##############################################################################
Two dimensional unit testing
python;unit testing