Ticket #228: 228-step-statistics.patch
| File 228-step-statistics.patch, 5.9 KB (added by dustin, 2 years ago) |
|---|
-
buildbot/status/builder.py
Wed Jun 25 23:30:36 EDT 2008 dustin@v.igoro.us * #228:step-statistics.patch Introduce steps statistics diff -rN -u old-dustin/buildbot/status/builder.py new-dustin/buildbot/status/builder.py
old new 449 449 self.finish() # releases self.openfile, which will be closed 450 450 del self.entries 451 451 452 453 452 class HTMLLogFile: 454 453 implements(interfaces.IStatusLog) 455 454 … … 642 641 I represent a collection of output status for a 643 642 L{buildbot.process.step.BuildStep}. 644 643 644 Statistics contain any information gleaned from a step that is 645 not in the form of a logfile. As an example, steps that run 646 tests might gather statistics about the number of passed, failed, 647 or skipped tests. 648 645 649 @type color: string 646 650 @cvar color: color that this step feels best represents its 647 651 current mood. yellow,green,red,orange are the … … 655 659 @cvar text2: list of short texts added to the overall build description 656 660 @type logs: dict of string -> L{buildbot.status.builder.LogFile} 657 661 @ivar logs: logs of steps 662 @type statistics: dict 663 @ivar statistics: results from running this step 658 664 """ 659 665 # note that these are created when the Build is set up, before each 660 666 # corresponding BuildStep has started. 661 667 implements(interfaces.IBuildStepStatus, interfaces.IStatusEvent) 662 persistenceVersion = 1668 persistenceVersion = 2 663 669 664 670 started = None 665 671 finished = None … … 671 677 watchers = [] 672 678 updates = {} 673 679 finishedWatchers = [] 680 statistics = {} 674 681 675 682 def __init__(self, parent): 676 683 assert interfaces.IBuildStatus(parent) … … 680 687 self.watchers = [] 681 688 self.updates = {} 682 689 self.finishedWatchers = [] 690 self.statistics = {} 683 691 684 692 def getName(self): 685 693 """Returns a short string with the name of this step. This string … … 764 772 """ 765 773 return (self.results, self.text2) 766 774 775 def hasStatistic(self, name): 776 """Return true if this step has a value for the given statistic. 777 """ 778 return self.statistics.has_key(name) 779 780 def getStatistic(self, name, default=None): 781 """Return the given statistic, if present 782 """ 783 return self.statistics.get(name, default) 784 767 785 # subscription interface 768 786 769 787 def subscribe(self, receiver, updateInterval=10): … … 847 865 def setText2(self, text): 848 866 self.text2 = text 849 867 868 def setStatistic(self, name, value): 869 """Set the given statistic. Usually called by subclasses. 870 """ 871 self.statistics[name] = value 872 850 873 def stepFinished(self, results): 851 874 self.finished = util.now() 852 875 self.results = results … … 886 909 if not hasattr(self, "urls"): 887 910 self.urls = {} 888 911 912 def upgradeToVersion2(self): 913 if not hasattr(self, "statistics"): 914 self.statistics = {} 915 889 916 890 917 class BuildStatus(styles.Versioned): 891 918 implements(interfaces.IBuildStatus, interfaces.IStatusEvent) … … 978 1005 def getTimes(self): 979 1006 return (self.started, self.finished) 980 1007 1008 _sentinel = [] # used as a sentinel to indicate unspecified initial_value 1009 def getSummaryStatistic(self, name, summary_fn, initial_value=_sentinel): 1010 """Summarize the named statistic over all steps in which it 1011 exists, using combination_fn and initial_value to combine multiple 1012 results into a single result. This translates to a call to Python's 1013 X{reduce}:: 1014 return reduce(summary_fn, step_stats_list, initial_value) 1015 """ 1016 step_stats_list = [ 1017 st.getStatistic(name) 1018 for st in self.steps 1019 if st.hasStatistic(name) ] 1020 if initial_value is self._sentinel: 1021 return reduce(summary_fn, step_stats_list) 1022 else: 1023 return reduce(summary_fn, step_stats_list, initial_value) 1024 981 1025 def isFinished(self): 982 1026 return (self.finished is not None) 983 1027 -
buildbot/test/test_status.py
diff -rN -u old-dustin/buildbot/test/test_status.py new-dustin/buildbot/test/test_status.py
old new 1 1 # -*- test-case-name: buildbot.test.test_status -*- 2 2 3 3 import email, os 4 import operator 4 5 5 6 from zope.interface import implements 6 7 from twisted.internet import defer, reactor … … 1194 1195 1195 1196 def send(self, msg): 1196 1197 self.message += msg 1198 1199 class StepStatistics(unittest.TestCase): 1200 def testStepStatistics(self): 1201 status = builder.BuildStatus(builder.BuilderStatus("test"), 123) 1202 status.addStepWithName('step1') 1203 status.addStepWithName('step2') 1204 status.addStepWithName('step3') 1205 status.addStepWithName('step4') 1206 1207 steps = status.getSteps() 1208 (step1, step2, step3, step4) = steps 1209 1210 step1.setStatistic('test-prop', 1) 1211 step3.setStatistic('test-prop', 2) 1212 step4.setStatistic('test-prop', 4) 1213 1214 step1.setStatistic('other-prop', 27) 1215 # Just to have some other properties around 1216 1217 self.failUnlessEqual(step1.getStatistic('test-prop'), 1, 1218 'Retrieve an existing property') 1219 self.failUnlessEqual(step1.getStatistic('test-prop', 99), 1, 1220 "Don't default an existing property") 1221 self.failUnlessEqual(step2.getStatistic('test-prop', 99), 99, 1222 'Default a non-existant property') 1223 1224 self.failUnlessEqual( 1225 status.getSummaryStatistic('test-prop', operator.add), 7, 1226 'Sum property across the build') 1227 1228 self.failUnlessEqual( 1229 status.getSummaryStatistic('test-prop', operator.add, 13), 20, 1230 'Sum property across the build with initial value')
![[Buildbot Logo]](/trac/chrome/site/header-text-transparent.png)