source: sasview/sansrealspace/src/realspace/test/testcase_generator.py @ 82789f1

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 82789f1 was ba1d1e9, checked in by Mathieu Doucet <doucetm@…>, 17 years ago

moving sansrealspace to trunk

  • Property mode set to 100644
File size: 10.0 KB
RevLine 
[ba1d1e9]1"""
2    Random test-case generator for Real-space simulation
3   
4    @copyright: University of Tennessee, 2007
5    @license: This software is provided as part of the DANSE project.
6"""
7import time
8
9class Stimulus:
10    """Base class for simuli objects"""
11   
12    frequency = 1.0
13   
14    def __init__(self):
15        """Initialization"""
16        name = self.__class__.__name__
17        pos = name.index('Stimulus')       
18        self.name = name[0:pos]
19       
20    def __call__(self, obj):
21        """
22            Stimulus application
23            @param obj: object to apply the stimulus to
24            @return: the modified object and the StimulusReport object
25        """
26        return obj, None
27   
28
29class StimulusReport:
30    """Report on the application of a stimulus"""
31    def __init__(self, tag=''):
32        """   
33            Initialization
34            @param tag: name of the applied stimulus
35        """
36        self.tag = tag
37        self.applied = 1
38        self.passed  = 0
39        self.trace = ''
40        self.log = ''
41       
42    def __str__(self):
43        """Returns a string with the success rate"""
44        return str(self.passed/self.applied)
45   
46    def __add__(self, other):
47        """Adds two reports"""
48        self.applied += other.applied
49        self.passed  += other.passed
50        if len(other.trace)>0:
51            self.trace = self.trace+'\n'+other.trace
52        if len(other.log)>0:
53            self.log = self.log+'\n'+other.log
54        return self
55
56    def isPassed(self):
57        """Returns true if report is a success"""
58        if self.applied == self.passed:
59            return True
60        return False
61
62
63class ReportCard: # pylint: disable-msg=R0902
64    """ Class to hold test-case results """
65   
66    def __init__(self):
67        """ Initialization """
68        ## Number of test cases
69        self.n_cases = 0
70        ## Number of passed test cases
71        self.n_cases_pass = 0
72       
73        ## Dictionary of stimuli
74        self.stimuli = {}
75       
76        ## Test log
77        self.log = ""
78        ## Trace
79        self.trace = ""
80        ## Model tested
81        self.model = ""
82        ## List of all models tested
83        self.modelList = []
84       
85       
86    def __add__(self, other):
87        """ Add two report cards
88            @param other: other report to add
89            @return: updated self
90        """
91        if other.__class__.__name__=='ReportCard':
92            # Adding two test-case report cards
93            self.n_cases += other.n_cases
94            self.n_cases_pass += other.n_cases_pass
95           
96            for tag in other.stimuli:
97                if tag in self.stimuli:
98                    self.stimuli[tag] += other.stimuli[tag]
99                else:
100                    self.stimuli[tag] = other.stimuli[tag]
101                   
102            if len(other.log)>0:
103                self.log += other.log
104            if len(other.trace)>0:
105                self.trace += other.trace
106               
107            if not other.model in self.modelList:
108                self.modelList.append(other.model)
109           
110        elif other.__class__.__name__ == 'StimulusReport':
111            # Adding a stimulus report to the report card
112            if other.tag in self.stimuli:
113                self.stimuli[other.tag] += other
114            else:
115                self.stimuli[other.tag] = other
116                   
117        else:
118            raise ValueError, \
119            "ReportCard: Unrecognized class %s" % other.__class__.__name__
120        return self
121       
122    def isPassed(self):
123        """ Returns true if no error was found """
124        if self.n_cases_pass < self.n_cases:
125            return False
126        return True
127       
128    def __str__(self):
129        """ String representation of the report card """
130        from sans.models.ModelFactory import ModelFactory
131       
132        log = ''
133       
134        rep = "Detailed output:\n"
135        rep += self.log
136        rep += "\n"
137        rep += "Total number of cases: %g\n" % self.n_cases
138        rep += "   Passed:             %g\n" % self.n_cases_pass
139        rep += "\n"
140        self.modelList.sort()
141        rep += "Models tested: %s\n" % self.modelList
142        rep += "\n"
143        rep += "\n"
144        rep += "Breakdown:\n"
145       
146        for tag in self.stimuli:
147           
148            rep += "   %-10s:          %g / %g\n" % (tag, self.stimuli[tag].passed, self.stimuli[tag].applied)
149            log += self.stimuli[tag].log
150       
151        rep += '\n'+log
152        return rep
153   
154       
155
156class TestCaseGenerator:
157    """ Generator for suite of test-cases
158    """
159   
160    def __init__(self, stimuli):
161        """ Initialization
162        """
163        self.stimuli = stimuli
164        self.n_tests = 0
165        self.n_passed = 0
166        self.time = 0
167        self.reportCard = ReportCard()
168   
169    def generateFiles(self, number, file_prefix):
170        """ Generate test-case files
171            @param number: number of files to generate
172            @param file_prefix: prefix for the file names
173        """
174       
175        for i in range(number):
176            filename = "%s_%d.xml" % (file_prefix, i)
177            self.generateFileTest(filename)
178            self.n_tests += 1
179           
180    def generateAndRun(self, number):
181        """ Generate test-cases and run them
182            @param number: number of test-cases to generate
183        """
184        start_time = time.time()
185        for i in range(number):
186            textcase = self.generateTest()
187            t = TestCase(self.stimuli, text = textcase)
188            passed = t.run()
189            self.reportCard += t.reportCard
190            if not passed:
191                t = time.localtime()
192                xmloutput = open("error_%i-%i-%i-%i-%i-%i_%i.xml" % \
193                 (t[0],t[1],t[2],t[3],t[4],t[5],self.reportCard.n_cases),'w')
194                xmloutput.write(textcase)
195                xmloutput.close()
196
197               
198        self.time += time.time()-start_time
199        print self.reportCard       
200       
201    def generateFileTest(self, filename = "tmp.xml"):
202        """
203            Write a random test-case in an XML file
204            @param filename: name of file to write to
205        """
206        text = self.generateTest()
207        # Write test case in file
208        xmlfile = open(filename,'w')
209        xmlfile.write(text)
210        xmlfile.close()
211   
212   
213    def generateTest(self):
214        """
215            Generate an XML representation of a random test-case
216        """
217        import random
218       
219        # Reset stimuli object
220        self.stimuli.reset()
221        #t = TestCase()
222        text = "<?xml version=\"1.0\"?>\n"
223        text  += "<TestCase>\n"
224        loop = True
225        while loop:
226           
227            stimulus = self.stimuli.getRandomStimulus()
228            if stimulus == None:
229                loop = False
230            else:   
231                text += "  <Stimulus id=\"%s\"/>\n" % stimulus
232        text += "</TestCase>"
233       
234        return text
235   
236       
237class TestCase:
238    """ Test-case class """
239   
240    def __init__(self, stimuliObject, filename = None, text = None):
241        """ Initialization
242            @param filename: name of file containing the test case
243        """
244        self.filename = filename
245        self.text = text
246        self.stimuli = stimuliObject
247        self.model = stimuliObject.setup()
248        self.passed = True
249        self.reportCard = ReportCard()
250       
251   
252    def run(self):
253        """ Read the test case and execute it """
254        from xml.dom.minidom import parse
255        from xml.dom.minidom import parseString
256       
257        # Initialize report
258        self.reportCard = ReportCard()
259        self.reportCard.model = "Canvas"
260        self.reportCard.n_cases = 1
261       
262        if not self.text == None:
263            dom = parseString(self.text)
264        elif not self.filename == None:
265            dom = parse(self.filename)
266        else:
267            print "No input to parse"
268            return False
269       
270        if dom.hasChildNodes():
271            for n in dom.childNodes:
272                if n.nodeName == "TestCase":
273                    self.processStimuli(n)
274           
275        # Update report card       
276        if self.passed:
277            self.reportCard.n_cases_pass = 1
278           
279        return self.passed
280                         
281    def processStimuli(self, node):
282        """ Process the stimuli list in the TestCase node
283            of an XML test-case file
284            @param node: test-case node
285        """
286        report = ReportCard()
287        report.trace = "%s\n" % self.model.name
288       
289        self.passed = True
290        if node.hasChildNodes():
291            for n in node.childNodes:
292                if n.nodeName == "Stimulus":
293                   
294                    s_type = None
295                    if n.hasAttributes():
296                        # Get stilumus ID
297                        for i in range(len(n.attributes)):
298                            attr_name = n.attributes.item(i).name
299                            if attr_name == "id":
300                                s_type = n.attributes.item(i).nodeValue
301                    if hasattr(self.stimuli,"%sStimulus" % s_type):
302                        stimulus = getattr(self.stimuli,"%sStimulus" % s_type)()
303                        #print s_type, self.model.name
304                        m, res = stimulus(self.model)
305                        #print "     ", m.name
306                        self.model = m
307                        if not res.isPassed():
308                            self.passed = False
309                       
310                        report += res
311                       
312                    else:
313                        print "Stimulus %s not found" % s_type
314                       
315        self.reportCard += report
316       
317        if not self.passed:
318            print report.trace
319        return self.passed
320       
321 
Note: See TracBrowser for help on using the repository browser.