Commits

seccanj committed 1cc63f2

Release 1.4.2. Fixed Ticket #8378. Also added support for custom test case outcomes in the Test Stats page.

o Fixed Ticket #8378 (Track-Hacks): Set date and time format correctly in Test Stats page
Also added support for custom test case outcomes in the Test Stats page

Comments (0)

Files changed (9)

 
 (Refer to the tickets on trac-hacks or SourceForge for complete descriptions.)
 
+Release 1.4.2 (2011-01-09):
+  o Fixed Ticket #8378 (Track-Hacks): Set date and time format correctly in Test Stats page
+  Also added support for custom test case outcomes in the Test Stats page
+
 Release 1.4.1 (2010-12-27):
   o Enhancement #7846 (Track-Hacks): Customizable test case outcomes (aka verdicts)
   o Enhancement #7570 (Track-Hacks): Add a relationship table between tickets and test cases in plan, and corresponding API

testman4trac/trunk/setup.py

 
 setup(
     name='TestManager',
-    version='1.4.1',
+    version='1.4.2',
     packages=['testmanager'],
     package_data={
         'testmanager' : [

testman4trac/trunk/testmanager/README.txt

 
 (Refer to the tickets on trac-hacks or SourceForge for complete descriptions.)
 
+Release 1.4.2 (2011-01-09):
+  o Fixed Ticket #8378 (Track-Hacks): Set date and time format correctly in Test Stats page
+  Also added support for custom test case outcomes in the Test Stats page
+
 Release 1.4.1 (2010-12-27):
   o Enhancement #7846 (Track-Hacks): Customizable test case outcomes (aka verdicts)
   o Enhancement #7570 (Track-Hacks): Add a relationship table between tickets and test cases in plan, and corresponding API

testman4trac/trunk/testmanager/locale/it/LC_MESSAGES/testmanager-js.mo

Binary file modified.

testman4trac/trunk/testmanager/macros.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010 Roberto Longobardi, Marco Cipriani
+# Copyright (C) 2010 Roberto Longobardi
 #
 
 import copy
 
 from trac.core import *
 from trac.mimeview.api import Context
-from trac.util import format_datetime
+from trac.util import format_datetime, format_date
 from trac.wiki.macros import WikiMacroBase
 from trac.wiki.api import WikiSystem, parse_args
 from trac.wiki.formatter import Formatter, format_to_html

testman4trac/trunk/testmanager/stats.py

 
 from trac.core import *
 from trac.config import Option, IntOption
+from trac.util import format_date, format_datetime
 from trac.web import IRequestHandler
 from trac.web.chrome import INavigationContributor, ITemplateProvider
 from trac.perm import IPermissionRequestor
 
 from datetime import date, datetime, time, timedelta
 from time import strptime
-from trac.util.datefmt import utc
+from trac.util.datefmt import utc, parse_date
 
 from tracgenericclass.util import *
 
 from testmanager.util import *
 
 
+
 # ************************
-DEFAULT_DAYS_BACK = 30*6 
-DEFAULT_INTERVAL = 30
+DEFAULT_DAYS_BACK = 30*3 
+DEFAULT_INTERVAL = 7
 # ************************
 
 class TestStatsPlugin(Component):
     implements(INavigationContributor, IRequestHandler, ITemplateProvider, IPermissionRequestor)
 
     yui_base_url = Option('teststats', 'yui_base_url',
-            default='http://yui.yahooapis.com/2.5.2',
+            default='http://yui.yahooapis.com/2.8.2r1',
             doc='Location of YUI API')
 
     default_days_back = IntOption('teststats', 'default_days_back',
         '''
 
         if catpath == None or catpath == '':
-            path_filter = "TC_%"
+            path_filter = "TC_%_TC%"
         else:
-            path_filter = catpath + "_%" 
+            path_filter = catpath + "%_TC%" 
 
         dates_condition = ''
 
         db = self.env.get_db_cnx()
         cursor = db.cursor()
         
-        # TODO: Fix this query because it also counts test catalogs
         cursor.execute("SELECT COUNT(*) FROM wiki WHERE name LIKE '%s' AND version = 1 %s" % (path_filter, dates_condition))
 
         row = cursor.fetchone()
         db = self.env.get_db_cnx()
         cursor = db.cursor()
 
-        #self.log.debug("From %s to %s, status=%s, plan=%s" % (from_date.isoformat(), at_date.isoformat(), status, testplan))
-        #self.log.debug("SELECT COUNT(*) from testcasehistory WHERE status = '%s' AND time > %s AND time <= %s %s" % (status, to_any_timestamp(from_date), to_any_timestamp(at_date), testplan_filter))
         cursor.execute("SELECT COUNT(*) from testcasehistory WHERE status = '%s' AND time > %s AND time <= %s %s" % (status, to_any_timestamp(from_date), to_any_timestamp(at_date), testplan_filter))
 
         row = cursor.fetchone()
         return re.match(r'/teststats(?:_trac)?(?:/.*)?$', req.path_info)
 
     def process_request(self, req):
-        test_manager_system = TestManagerSystem(self.env)
-        #test_manager_system.report_testcase_status()
+        testmanagersystem = TestManagerSystem(self.env)
+        tc_statuses = testmanagersystem.get_tc_statuses_by_color()
         
         req_content = req.args.get('content')
         testplan = None
             if not grab_resolution.isdigit():
                 raise TracError('The graph interval field must be an integer, days.')
 
-            # TODO: I'm letting the exception raised by 
-            #  strptime() appear as the Trac error.
-            #  Maybe a wrapper should be written.
-
-            at_date = datetime(*strptime(grab_at_date, "%m/%d/%Y")[0:6])
-            at_date = datetime.combine(at_date, time(11,59,59,0,utc)) # Add tzinfo
-
-            from_date = datetime(*strptime(grab_from_date, "%m/%d/%Y")[0:6])
-            from_date = datetime.combine(from_date, time(0,0,0,0,utc)) # Add tzinfo
+            at_date = parse_date(grab_at_date, req.tz)
+            from_date = parse_date(grab_from_date, req.tz)
 
             graph_res = int(grab_resolution)
 
         else:
             # default data
-            todays_date = date.today()
-            at_date = datetime.combine(todays_date,time(11,59,59,0,utc))
+            todays_date = datetime.today()
+            at_date = todays_date #+ timedelta(1) # datetime.combine(todays_date,time(23,59,59,0,req.tz))
+            at_date = at_date.replace(tzinfo = req.tz)
             from_date = at_date - timedelta(self.default_days_back)
             graph_res = self.default_interval
-    
-            at_date_str = at_date.strftime("%m/%d/%Y")
-            from_date_str=  from_date.strftime("%m/%d/%Y")
-
-            # 2.5 only: at_date = datetime.strptime(at_date_str, "%m/%d/%Y")
-            at_date = datetime(*strptime(at_date_str, "%m/%d/%Y")[0:6])
-            at_date = datetime.combine(at_date, time(11,59,59,0,utc)) # Add tzinfo
-            
-            # 2.5 only: from_date = datetime.strptime(from_date_str, "%m/%d/%Y")
-            from_date = datetime(*strptime(from_date_str, "%m/%d/%Y")[0:6])
-            from_date = datetime.combine(from_date, time(0,0,0,0,utc)) # Add tzinfo
             
         count = []
 
 
         # Calculate remaining points
         for cur_date in daterange(from_date, at_date, graph_res):
+            # Handling custom test case outcomes here
             num_new = self._get_num_testcases(last_date, cur_date, catpath, testplan, req)
-            num_successful = self._get_num_tcs_by_status(last_date, cur_date, 'SUCCESSFUL', testplan, req)
-            num_failed = self._get_num_tcs_by_status(last_date, cur_date, 'FAILED', testplan, req)
+            
+            num_successful = 0
+            for tc_outcome in tc_statuses['green']:
+                num_successful += self._get_num_tcs_by_status(last_date, cur_date, tc_outcome, testplan, req)
+
+            num_failed = 0
+            for tc_outcome in tc_statuses['red']:
+                num_failed += self._get_num_tcs_by_status(last_date, cur_date, tc_outcome, testplan, req)
             
             num_all = self._get_num_testcases(None, cur_date, catpath, testplan, req)
-            num_all_successful = self._get_num_tcs_by_status(from_date, cur_date, 'SUCCESSFUL', testplan, req)
-            num_all_failed = self._get_num_tcs_by_status(from_date, cur_date, 'FAILED', testplan, req)
+
+            num_all_successful = 0
+            for tc_outcome in tc_statuses['green']:
+                num_all_successful += self._get_num_tcs_by_status(from_date, cur_date, tc_outcome, testplan, req)
+
+            num_all_failed = 0
+            for tc_outcome in tc_statuses['red']:
+                num_all_failed += self._get_num_tcs_by_status(from_date, cur_date, tc_outcome, testplan, req)
 
             num_all_untested = num_all - num_all_successful - num_all_failed
 
-            datestr = cur_date.strftime("%m/%d/%Y") 
+            datestr = format_date(cur_date) 
             if graph_res != 1:
-                datestr = "%s thru %s" % (last_date.strftime("%m/%d/%Y"), datestr) 
-            count.append( {'from_date': last_date.strftime("%m/%d/%Y"),
-                         'to_date': cur_date.strftime("%m/%d/%Y"),
+                datestr = "%s thru %s" % (format_date(last_date), datestr) 
+            count.append( {'from_date': format_date(last_date),
+                         'to_date': datestr,
                          'date'  : datestr,
                          'new_tcs'    : num_new,
                          'successful': num_successful,
         # for templating
         if (not req_content == None) and (req_content == "chartdata"):
             jsdstr = '{"chartdata": [\n'
+
             for x in count:
                 jsdstr += '{"date": "%s",' % x['date']
                 jsdstr += ' "new_tcs": %s,' % x['new_tcs']
                 jsdstr += ' "all_untested": %s,' % x['all_untested']
                 jsdstr += ' "all_failed": %s},\n' % x['all_failed']
             jsdstr = jsdstr[:-2] +'\n]}'
+
+            if isinstance(jsdstr, unicode): 
+                jsdstr = jsdstr.encode('utf-8') 
+
             req.send_header("Content-Length", len(jsdstr))
             req.write(jsdstr)
-            return 
+            return
         elif (not req_content == None) and (req_content == "downloadcsv"):
             csvstr = "Date from;Date to;New Test Cases;Successful;Failed;Total Test Cases;Total Successful;Total Untested;Total Failed\r\n"
             for x in count:
                 csvstr += '%s;' % x['all_successful']
                 csvstr += '%s;' % x['all_untested']
                 csvstr += '%s\r\n' % x['all_failed']
+                
+            if isinstance(csvstr, unicode): 
+                csvstr = csvstr.encode('utf-8') 
+
             req.send_header("Content-Length", len(csvstr))
             req.send_header("Content-Disposition", "attachment;filename=Test_stats.csv")
             req.write(csvstr)
-            return 
+            return
         else:
             db = self.env.get_db_cnx()
             showall = req.args.get('show') == 'all'
 
             testplan_list = []
-            for planid, catid, catpath, name, author, ts_str in test_manager_system.list_all_testplans():
+            for planid, catid, catpath, name, author, ts_str in testmanagersystem.list_all_testplans():
                 testplan_list.append({'planid': planid, 'catpath': catpath, 'name': name})
 
             data = {}
             data['testcase_data'] = count
-            data['start_date'] = from_date.strftime("%m/%d/%Y")
-            data['end_date'] = at_date.strftime("%m/%d/%Y")
+            data['start_date'] = format_date(from_date)
+            data['end_date'] = format_date(at_date)
             data['resolution'] = str(graph_res)
             data['baseurl'] = req.base_url
             data['testplans'] = testplan_list

testman4trac/trunk/testmanager/templates/testmanagerstats.html

 	#chart { height: 500px }
 	</style>
 	
-	<script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/yahoo-dom-event/yahoo-dom-event.js"></script>
-	<script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/element/element-beta-min.js"></script>
-	<script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/datasource/datasource-beta-min.js"></script>
-	<script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/json/json-min.js"></script>
-	<!-- OPTIONAL: Connection (enables XHR) -->
-	<script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/connection/connection-min.js"></script>
-	<!-- Source files -->
-	<script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/charts/charts-experimental-min.js"></script>
+    <script src="http://yui.yahooapis.com/2.8.2r1/build/yahoo-dom-event/yahoo-dom-event.js"></script>
+    <script src="http://yui.yahooapis.com/2.8.2r1/build/element/element-min.js"></script>
+    <script src="http://yui.yahooapis.com/2.8.2r1/build/datasource/datasource-min.js"></script>
+    <script src="http://yui.yahooapis.com/2.8.2r1/build/json/json-min.js"></script>
+    <script src="http://yui.yahooapis.com/2.8.2r1/build/swf/swf-min.js"></script>
+    <!-- OPTIONAL: Connection (enables XHR) -->
+    <script src="http://yui.yahooapis.com/2.8.2r1/build/connection/connection-min.js"></script>
+    <!-- Source files -->
+    <script src="http://yui.yahooapis.com/2.8.2r1/build/charts/charts-min.js"></script>
+
 
     <script type="text/javascript">
         var urlAddress = "${baseurl}" + "/teststats?content=render";
 setProvided();
 updateStaticURL();
 
-YAHOO.widget.Chart.SWFURL = "http://yui.yahooapis.com/2.5.2/build/charts/assets/charts.swf";
+YAHOO.widget.Chart.SWFURL = "http://yui.yahooapis.com/2.8.2r1/build/charts/assets/charts.swf";
 
 var myDataSource = new YAHOO.util.DataSource( "?content=chartdata" );
 

tracgenericclass/trunk/tracgenericclass/model.py

             'search': search for objects of this class.
         
         :param key_str: optional, the object's key, in the form of a string representing 
-                        a dictionary. To get this string, use the 
-                        get_string_from_dictionary() function in the
+                        a dictionary. To get a dictionary back from this string, use the 
+                        get_dictionary_from_string() function in the
                         tracgenericclass.util package.
-        :param operation: optional, the operatyion to be performed on the object.
-                          TODO: specify the list of available operations.
+        :param operation: optional, the operation to be performed on the object.
         :param name: optional property name, valid for the 'set' operation type
         :param value: optional property value, valid for the 'set' operation type
         """
     def get_search_results(self, req, terms, filters):
         """
         Called in the context of the trac search API, to return a list
-        of objects of this class matching the specified terms.
+        of objects of this class matching the specified terms.
         
         Concrete classes should override this method to perform class-specific
         searches.

tracgenericworkflow/trunk/tracgenericworkflow/model.py

 class ResourceWorkflowState(AbstractVariableFieldsObject):
     """
     This object represents the current workflow state of the associated
-    resorce.
+    resource.
     """
     
     # Fields that must not be modified directly by the user