swagger-ize dashboard and version apis of testAPI 27/14827/2
authorSerenaFeng <feng.xiaowei@zte.com.cn>
Mon, 30 May 2016 11:14:52 +0000 (19:14 +0800)
committerSerenaFeng <feng.xiaowei@zte.com.cn>
Mon, 30 May 2016 12:05:11 +0000 (20:05 +0800)
JIRA: FUNCTEST-273

Change-Id: I6f2b1de5488ba684d0c00e9f40daee2487a011cc
Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
utils/test/result_collection_api/common/config.py
utils/test/result_collection_api/dashboard/dashboard_utils.py
utils/test/result_collection_api/resources/dashboard_handlers.py [new file with mode: 0644]
utils/test/result_collection_api/resources/handlers.py
utils/test/result_collection_api/resources/models.py
utils/test/result_collection_api/resources/result_handlers.py
utils/test/result_collection_api/result_collection_api.py
utils/test/result_collection_api/tests/unit/test_base.py
utils/test/result_collection_api/tests/unit/test_dashboard.py
utils/test/result_collection_api/tests/unit/test_result.py

index a62e805..369bdd2 100644 (file)
@@ -5,27 +5,13 @@
 # are made available under the terms of the Apache License, Version 2.0
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
+# feng.xiaowei@zte.com.cn remove prepare_put_request            5-30-2016
 ##############################################################################
 
 
 from ConfigParser import SafeConfigParser, NoOptionError
 
 
-def prepare_put_request(edit_request, key, new_value, old_value):
-    """
-    This function serves to prepare the elements in the update request.
-    We try to avoid replace the exact values in the db
-    edit_request should be a dict in which we add an entry (key) after
-    comparing values
-    """
-    if not (new_value is None):
-        if len(new_value) > 0:
-            if new_value != old_value:
-                edit_request[key] = new_value
-
-    return edit_request
-
-
 class ParseError(Exception):
     """
     Custom exception class for config file
index bfa7432..9de5b19 100644 (file)
@@ -67,7 +67,7 @@ def get_dashboard_cases():
     return modules
 
 
-def get_dashboard_result(project, case, results):
+def get_dashboard_result(project, case, results=None):
     # get the dashboard ready results
     # paramters are:
     # project: project name
diff --git a/utils/test/result_collection_api/resources/dashboard_handlers.py b/utils/test/result_collection_api/resources/dashboard_handlers.py
new file mode 100644 (file)
index 0000000..320fcc2
--- /dev/null
@@ -0,0 +1,99 @@
+from tornado.web import HTTPError
+
+from common.constants import HTTP_NOT_FOUND
+from dashboard.dashboard_utils import check_dashboard_ready_project, \
+    check_dashboard_ready_case, get_dashboard_result
+from resources.result_handlers import GenericResultHandler
+from resources.result_models import TestResult
+from tornado_swagger_ui.tornado_swagger import swagger
+
+
+class GenericDashboardHandler(GenericResultHandler):
+    def __init__(self, application, request, **kwargs):
+        super(GenericDashboardHandler, self).__init__(application,
+                                                      request,
+                                                      **kwargs)
+        self.table = self.db_results
+        self.table_cls = TestResult
+
+
+class DashboardHandler(GenericDashboardHandler):
+    @swagger.operation(nickname='query')
+    def get(self):
+        """
+            @description: Retrieve dashboard ready result(s)
+                          for a test project
+            @notes: Retrieve dashboard ready result(s) for a test project
+                Available filters for this request are :
+                 - project : project name
+                 - case : case name
+                 - pod : pod name
+                 - version : platform version (Arno-R1, ...)
+                 - installer (fuel, ...)
+                 - period : x (x last days)
+
+                GET /dashboard?project=functest&case=vPing&version=Colorado \
+                &pod=pod_name&period=15
+            @rtype: L{string}
+            @param pod: pod name
+            @type pod: L{string}
+            @in pod: query
+            @required pod: False
+            @param project: project name
+            @type project: L{string}
+            @in project: query
+            @required project: True
+            @param case: case name
+            @type case: L{string}
+            @in case: query
+            @required case: True
+            @param version: i.e. Colorado
+            @type version: L{string}
+            @in version: query
+            @required version: False
+            @param installer: fuel/apex/joid/compass
+            @type installer: L{string}
+            @in installer: query
+            @required installer: False
+            @param period: last days
+            @type period: L{string}
+            @in period: query
+            @required period: False
+            @return 200: test result exist
+            @raise 400: period is not in
+            @raise 404: project or case name missing,
+                        or project or case is not dashboard ready
+        """
+
+        project_arg = self.get_query_argument("project", None)
+        case_arg = self.get_query_argument("case", None)
+
+        # on /dashboard retrieve the list of projects and testcases
+        # ready for dashboard
+        if project_arg is None:
+            raise HTTPError(HTTP_NOT_FOUND, "Project name missing")
+
+        if not check_dashboard_ready_project(project_arg):
+            raise HTTPError(HTTP_NOT_FOUND,
+                            'Project [{}] not dashboard ready'
+                            .format(project_arg))
+
+        if case_arg is None:
+            raise HTTPError(
+                HTTP_NOT_FOUND,
+                'Test case missing for project [{}]'.format(project_arg))
+
+        if not check_dashboard_ready_case(project_arg, case_arg):
+            raise HTTPError(
+                HTTP_NOT_FOUND,
+                'Test case [{}] not dashboard ready for project [{}]'
+                .format(case_arg, project_arg))
+
+        # special case of status for project
+        if case_arg == 'status':
+            self.finish_request(get_dashboard_result(project_arg, case_arg))
+        else:
+            def get_result(res, project, case):
+                return get_dashboard_result(project, case, res)
+
+            self._list(self.set_query(), get_result, project_arg, case_arg)
index b5f7145..b4f7117 100644 (file)
 # feng.xiaowei@zte.com.cn refactor dashboard related handler 5-24-2016
 # feng.xiaowei@zte.com.cn add methods to GenericApiHandler   5-26-2016
 # feng.xiaowei@zte.com.cn remove PodHandler                  5-26-2016
+# feng.xiaowei@zte.com.cn remove ProjectHandler              5-26-2016
+# feng.xiaowei@zte.com.cn remove TestcaseHandler             5-27-2016
+# feng.xiaowei@zte.com.cn remove ResultHandler               5-29-2016
+# feng.xiaowei@zte.com.cn remove DashboardHandler            5-30-2016
 ##############################################################################
 
 import json
-from datetime import datetime, timedelta
+from datetime import datetime
 
 from tornado.web import RequestHandler, asynchronous, HTTPError
 from tornado import gen
 
 from models import CreateResponse
-from resources.result_models import TestResult
 from common.constants import DEFAULT_REPRESENTATION, HTTP_BAD_REQUEST, \
     HTTP_NOT_FOUND, HTTP_FORBIDDEN
-from common.config import prepare_put_request
-from dashboard.dashboard_utils import check_dashboard_ready_project, \
-    check_dashboard_ready_case, get_dashboard_result
-
-
-def format_data(data, cls):
-    cls_data = cls.from_dict(data)
-    return cls_data.format_http()
+from tornado_swagger_ui.tornado_swagger import swagger
 
 
 class GenericApiHandler(RequestHandler):
@@ -70,15 +66,16 @@ class GenericApiHandler(RequestHandler):
         href = self.request.full_url() + '/' + str(resource)
         return CreateResponse(href=href).format()
 
+    def format_data(self, data):
+        cls_data = self.table_cls.from_dict(data)
+        return cls_data.format_http()
+
     @asynchronous
     @gen.coroutine
     def _create(self, miss_checks, db_checks, **kwargs):
         """
         :param miss_checks: [miss1, miss2]
-        :param db_checks: [(table, exist, query, (error, message))]
-        :param db_op: (insert/remove)
-        :param res_op: (_create_response/None)
-        :return:
+        :param db_checks: [(table, exist, query, error)]
         """
         if self.json_args is None:
             raise HTTPError(HTTP_BAD_REQUEST, "no body")
@@ -94,7 +91,7 @@ class GenericApiHandler(RequestHandler):
             data.__setattr__(k, v)
 
         for table, exist, query, error in db_checks:
-            check = yield self._eval_db(table, 'find_one', query(data))
+            check = yield self._eval_db_find_one(query(data), table)
             if (exist and not check) or (not exist and check):
                 code, message = error(data)
                 raise HTTPError(code, message)
@@ -109,29 +106,33 @@ class GenericApiHandler(RequestHandler):
 
     @asynchronous
     @gen.coroutine
-    def _list(self, query=None):
+    def _list(self, query=None, res_op=None, *args):
         if query is None:
             query = {}
-        res = []
+        data = []
         cursor = self._eval_db(self.table, 'find', query)
         while (yield cursor.fetch_next):
-            res.append(format_data(cursor.next_object(), self.table_cls))
-        self.finish_request({self.table: res})
+            data.append(self.format_data(cursor.next_object()))
+        if res_op is None:
+            res = {self.table: data}
+        else:
+            res = res_op(data, *args)
+        self.finish_request(res)
 
     @asynchronous
     @gen.coroutine
     def _get_one(self, query):
-        data = yield self._eval_db(self.table, 'find_one', query)
+        data = yield self._eval_db_find_one(query)
         if data is None:
             raise HTTPError(HTTP_NOT_FOUND,
                             "[{}] not exist in table [{}]"
                             .format(query, self.table))
-        self.finish_request(format_data(data, self.table_cls))
+        self.finish_request(self.format_data(data))
 
     @asynchronous
     @gen.coroutine
     def _delete(self, query):
-        data = yield self._eval_db(self.table, 'find_one', query)
+        data = yield self._eval_db_find_one(query)
         if data is None:
             raise HTTPError(HTTP_NOT_FOUND,
                             "[{}] not exit in table [{}]"
@@ -147,7 +148,7 @@ class GenericApiHandler(RequestHandler):
             raise HTTPError(HTTP_BAD_REQUEST, "No payload")
 
         # check old data exist
-        from_data = yield self._eval_db(self.table, 'find_one', query)
+        from_data = yield self._eval_db_find_one(query)
         if from_data is None:
             raise HTTPError(HTTP_NOT_FOUND,
                             "{} could not be found in table [{}]"
@@ -157,7 +158,7 @@ class GenericApiHandler(RequestHandler):
         # check new data exist
         equal, new_query = self._update_query(db_keys, data)
         if not equal:
-            to_data = yield self._eval_db(self.table, 'find_one', new_query)
+            to_data = yield self._eval_db_find_one(new_query)
             if to_data is not None:
                 raise HTTPError(HTTP_FORBIDDEN,
                                 "{} already exists in table [{}]"
@@ -165,22 +166,37 @@ class GenericApiHandler(RequestHandler):
 
         # we merge the whole document """
         edit_request = data.format()
-        edit_request.update(self._update_request(data))
+        edit_request.update(self._update_requests(data))
 
         """ Updating the DB """
         yield self._eval_db(self.table, 'update', query, edit_request)
         edit_request['_id'] = str(data._id)
         self.finish_request(edit_request)
 
-    def _update_request(self, data):
+    def _update_requests(self, data):
         request = dict()
         for k, v in self.json_args.iteritems():
-            request = prepare_put_request(request, k, v,
+            request = self._update_request(request, k, v,
                                           data.__getattribute__(k))
         if not request:
             raise HTTPError(HTTP_FORBIDDEN, "Nothing to update")
         return request
 
+    @staticmethod
+    def _update_request(edit_request, key, new_value, old_value):
+        """
+        This function serves to prepare the elements in the update request.
+        We try to avoid replace the exact values in the db
+        edit_request should be a dict in which we add an entry (key) after
+        comparing values
+        """
+        if not (new_value is None):
+            if len(new_value) > 0:
+                if new_value != old_value:
+                    edit_request[key] = new_value
+
+        return edit_request
+
     def _update_query(self, keys, data):
         query = dict()
         equal = True
@@ -197,111 +213,17 @@ class GenericApiHandler(RequestHandler):
     def _eval_db(self, table, method, *args):
         return eval('self.db.%s.%s(*args)' % (table, method))
 
-
-class VersionHandler(GenericApiHandler):
-    """ Display a message for the API version """
-    def get(self):
-        self.finish_request([{'v1': 'basics'}])
+    def _eval_db_find_one(self, query, table=None):
+        if table is None:
+            table = self.table
+        return self._eval_db(table, 'find_one', query)
 
 
-class DashboardHandler(GenericApiHandler):
-    """
-    DashboardHandler Class
-    Handle the requests about the Test project's results
-    in a dahboard ready format
-    HTTP Methdods :
-        - GET : Get all test results and details about a specific one
-    """
-    def initialize(self):
-        """ Prepares the database for the entire class """
-        super(DashboardHandler, self).initialize()
-        self.name = "dashboard"
-
-    @asynchronous
-    @gen.coroutine
+class VersionHandler(GenericApiHandler):
+    @swagger.operation(nickname='list')
     def get(self):
         """
-        Retrieve dashboard ready result(s) for a test project
-        Available filters for this request are :
-         - project : project name
-         - case : case name
-         - pod : pod name
-         - version : platform version (Arno-R1, ...)
-         - installer (fuel, ...)
-         - period : x (x last days)
-
-
-        :param result_id: Get a result by ID
-        :raise HTTPError
-
-        GET /dashboard?project=functest&case=vPing&version=Arno-R1 \
-        &pod=pod_name&period=15
-        => get results with optional filters
+            @description: Display a message for the API version
+            @rtype: L{Versions}
         """
-
-        project_arg = self.get_query_argument("project", None)
-        case_arg = self.get_query_argument("case", None)
-        pod_arg = self.get_query_argument("pod", None)
-        version_arg = self.get_query_argument("version", None)
-        installer_arg = self.get_query_argument("installer", None)
-        period_arg = self.get_query_argument("period", None)
-
-        # prepare request
-        query = dict()
-
-        if project_arg is not None:
-            query["project_name"] = project_arg
-
-        if case_arg is not None:
-            query["case_name"] = case_arg
-
-        if pod_arg is not None:
-            query["pod_name"] = pod_arg
-
-        if version_arg is not None:
-            query["version"] = version_arg
-
-        if installer_arg is not None:
-            query["installer"] = installer_arg
-
-        if period_arg is not None:
-            try:
-                period_arg = int(period_arg)
-            except:
-                raise HTTPError(HTTP_BAD_REQUEST)
-            if period_arg > 0:
-                period = datetime.now() - timedelta(days=period_arg)
-                obj = {"$gte": str(period)}
-                query["creation_date"] = obj
-
-        # on /dashboard retrieve the list of projects and testcases
-        # ready for dashboard
-        if project_arg is None:
-            raise HTTPError(HTTP_NOT_FOUND, "Project name missing")
-
-        if not check_dashboard_ready_project(project_arg):
-            raise HTTPError(HTTP_NOT_FOUND,
-                            'Project [{}] not dashboard ready'
-                            .format(project_arg))
-
-        if case_arg is None:
-            raise HTTPError(
-                HTTP_NOT_FOUND,
-                'Test case missing for project [{}]'.format(project_arg))
-
-        if not check_dashboard_ready_case(project_arg, case_arg):
-            raise HTTPError(
-                HTTP_NOT_FOUND,
-                'Test case [{}] not dashboard ready for project [{}]'
-                .format(case_arg, project_arg))
-
-        # special case of status for project
-        res = []
-        if case_arg != "status":
-            cursor = self.db.results.find(query)
-            while (yield cursor.fetch_next):
-                result = TestResult.from_dict(cursor.next_object())
-                res.append(result.format_http())
-
-        # final response object
-        self.finish_request(get_dashboard_result(project_arg, case_arg, res))
+        self.finish_request([{'v1': 'basics'}])
index b4094dd..3c834fd 100644 (file)
@@ -13,6 +13,7 @@
 # feng.xiaowei@zte.com.cn  mv TestCase to testcase_models.py       5-20-2016\r
 # feng.xiaowei@zte.com.cn  mv TestResut to result_models.py        5-23-2016\r
 ##############################################################################\r
+from tornado_swagger_ui.tornado_swagger import swagger\r
 \r
 \r
 class CreateResponse(object):\r
@@ -30,3 +31,19 @@ class CreateResponse(object):
 \r
     def format(self):\r
         return {'href': self.href}\r
+\r
+\r
+@swagger.model()\r
+class Versions(object):\r
+    """\r
+        @ptype versions: C{list} of L{Version}\r
+    """\r
+    def __init__(self, versions):\r
+        self.versions = versions\r
+\r
+\r
+@swagger.model()\r
+class Version(object):\r
+    def __init__(self, version=None, description=None):\r
+        self.version = version\r
+        self.description = description\r
index d3fea1d..d344f46 100644 (file)
@@ -17,67 +17,93 @@ class GenericResultHandler(GenericApiHandler):
         self.table = self.db_results
         self.table_cls = TestResult
 
+    def set_query(self):
+        query = dict()
+        for k in self.request.query_arguments.keys():
+            v = self.get_query_argument(k)
+            if k == 'project' or k == 'pod' or k == 'case':
+                query[k + '_name'] = v
+            elif k == 'period':
+                try:
+                    v = int(v)
+                except:
+                    raise HTTPError(HTTP_BAD_REQUEST, 'period must be int')
+                if v > 0:
+                    period = datetime.now() - timedelta(days=v)
+                    obj = {"$gte": str(period)}
+                    query['creation_date'] = obj
+            else:
+                query[k] = v
+        return query
+
 
 class ResultsCLHandler(GenericResultHandler):
     @swagger.operation(nickname="list-all")
     def get(self):
         """
-            @description: list all test results consist with query
+            @description: Retrieve result(s) for a test project
+                          on a specific pod.
+            @notes: Retrieve result(s) for a test project on a specific pod.
+                Available filters for this request are :
+                 - project : project name
+                 - case : case name
+                 - pod : pod name
+                 - version : platform version (Arno-R1, ...)
+                 - installer (fuel, ...)
+                 - build_tag : Jenkins build tag name
+                 - period : x (x last days)
+                 - scenario : the test scenario (previously version)
+                 - criteria : the global criteria status passed or failed
+                 - trust_indicator : evaluate the stability of the test case to avoid
+                 running systematically long and stable test case
+
+                GET /results/project=functest&case=vPing&version=Arno-R1 \
+                &pod=pod_name&period=15
             @return 200: all test results consist with query,
                          empty list if no result is found
             @rtype: L{TestResults}
+            @param pod: pod name
+            @type pod: L{string}
+            @in pod: query
+            @required pod: False
+            @param project: project name
+            @type project: L{string}
+            @in project: query
+            @required project: True
+            @param case: case name
+            @type case: L{string}
+            @in case: query
+            @required case: True
+            @param version: i.e. Colorado
+            @type version: L{string}
+            @in version: query
+            @required version: False
+            @param installer: fuel/apex/joid/compass
+            @type installer: L{string}
+            @in installer: query
+            @required installer: False
+            @param build_tag: i.e. v3.0
+            @type build_tag: L{string}
+            @in build_tag: query
+            @required build_tag: False
+            @param scenario: i.e. odl
+            @type scenario: L{string}
+            @in scenario: query
+            @required scenario: False
+            @param criteria: i.e. passed
+            @type criteria: L{string}
+            @in criteria: query
+            @required criteria: False
+            @param period: last days
+            @type period: L{string}
+            @in period: query
+            @required period: False
+            @param trust_indicator: must be integer
+            @type trust_indicator: L{string}
+            @in trust_indicator: query
+            @required trust_indicator: False
         """
-        query = dict()
-        pod_arg = self.get_query_argument("pod", None)
-        project_arg = self.get_query_argument("project", None)
-        case_arg = self.get_query_argument("case", None)
-        version_arg = self.get_query_argument("version", None)
-        installer_arg = self.get_query_argument("installer", None)
-        build_tag_arg = self.get_query_argument("build_tag", None)
-        scenario_arg = self.get_query_argument("scenario", None)
-        criteria_arg = self.get_query_argument("criteria", None)
-        period_arg = self.get_query_argument("period", None)
-        trust_indicator_arg = self.get_query_argument("trust_indicator", None)
-
-        if project_arg is not None:
-            query["project_name"] = project_arg
-
-        if case_arg is not None:
-            query["case_name"] = case_arg
-
-        if pod_arg is not None:
-            query["pod_name"] = pod_arg
-
-        if version_arg is not None:
-            query["version"] = version_arg
-
-        if installer_arg is not None:
-            query["installer"] = installer_arg
-
-        if build_tag_arg is not None:
-            query["build_tag"] = build_tag_arg
-
-        if scenario_arg is not None:
-            query["scenario"] = scenario_arg
-
-        if criteria_arg is not None:
-            query["criteria_tag"] = criteria_arg
-
-        if trust_indicator_arg is not None:
-            query["trust_indicator_arg"] = trust_indicator_arg
-
-        if period_arg is not None:
-            try:
-                period_arg = int(period_arg)
-            except:
-                raise HTTPError(HTTP_BAD_REQUEST)
-
-            if period_arg > 0:
-                period = datetime.now() - timedelta(days=period_arg)
-                obj = {"$gte": str(period)}
-                query["creation_date"] = obj
-
-        self._list(query)
+        self._list(self.set_query())
 
     @swagger.operation(nickname="create")
     def post(self):
index 652aa58..7d29c9d 100644 (file)
@@ -34,11 +34,12 @@ import argparse
 import tornado.ioloop
 import motor
 
-from resources.handlers import VersionHandler, DashboardHandler
+from resources.handlers import VersionHandler
 from resources.testcase_handlers import TestcaseCLHandler, TestcaseGURHandler
 from resources.pod_handlers import PodCLHandler, PodGURHandler
 from resources.project_handlers import ProjectCLHandler, ProjectGURHandler
 from resources.result_handlers import ResultsCLHandler, ResultsGURHandler
+from resources.dashboard_handlers import DashboardHandler
 from common.config import APIConfig
 from tornado_swagger_ui.tornado_swagger import swagger
 
@@ -92,7 +93,6 @@ def make_app():
             # get /dashboard
             #  => get the list of project with dashboard ready results
             (r"/dashboard/v1/results", DashboardHandler),
-            (r"/dashboard/v1/results([^/]*)", DashboardHandler),
         ],
         db=db,
         debug=CONF.api_debug_on,
index 036c6cf..ef711ae 100644 (file)
@@ -1,12 +1,14 @@
 import json
+
 from tornado.web import Application
 from tornado.testing import AsyncHTTPTestCase
 
 from resources.pod_handlers import PodCLHandler, PodGURHandler
 from resources.project_handlers import ProjectCLHandler, ProjectGURHandler
-from resources.handlers import VersionHandler, DashboardHandler
+from resources.handlers import VersionHandler
 from resources.testcase_handlers import TestcaseCLHandler, TestcaseGURHandler
 from resources.result_handlers import ResultsCLHandler, ResultsGURHandler
+from resources.dashboard_handlers import DashboardHandler
 from resources.models import CreateResponse
 import fake_pymongo
 
@@ -39,7 +41,6 @@ class TestBase(AsyncHTTPTestCase):
                 (r"/api/v1/results", ResultsCLHandler),
                 (r"/api/v1/results/([^/]+)", ResultsGURHandler),
                 (r"/dashboard/v1/results", DashboardHandler),
-                (r"/dashboard/v1/results([^/]*)", DashboardHandler),
             ],
             db=fake_pymongo,
             debug=True,
index 5c3f924..3e71333 100644 (file)
@@ -44,6 +44,7 @@ class TestDashboardQuery(TestDashboardBase):
     def test_success(self):
         code, body = self.query(self._set_query())
         self.assertEqual(code, HTTP_OK)
+        print(body)
         self.assertIn('{"description": "vPing results for Dashboard"}', body)
 
     def test_caseIsStatus(self):
index 5757df0..a7541b3 100644 (file)
@@ -1,4 +1,5 @@
 import unittest
+import copy
 
 from test_base import TestBase
 from resources.pod_models import PodCreateRequest
@@ -8,7 +9,6 @@ from resources.result_models import ResultCreateRequest, \
     TestResult, TestResults
 from common.constants import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND
 
-
 __author__ = '__serena__'
 
 
@@ -154,6 +154,27 @@ class TestResultCreate(TestResultBase):
         self.assertEqual(code, HTTP_OK)
         self.assert_href(body)
 
+    def test_createSameResults(self):
+        # req_again = ResultCreateRequest(pod_name=self.pod,
+        #                                  project_name=self.project,
+        #                                  case_name=self.case,
+        #                                  installer=self.installer,
+        #                                  version=self.version,
+        #                                  start_date="2016-05-23 08:16:09.477097",
+        #                                  stop_date=self.stop_date,
+        #                                  details=self.details.format(),
+        #                                  build_tag=self.build_tag,
+        #                                  scenario=self.scenario,
+        #                                  criteria=self.criteria,
+        #                                  trust_indicator=self.trust_indicator)
+        req_again = copy.deepcopy(self.req_d)
+        req_again.start_date = "2016-05-23 08:16:09.477097"
+        req_again.stop_date = "2016-05-23 08:16:19.477097"
+
+        (code, body) = self.create(req_again)
+        self.assertEqual(code, HTTP_OK)
+        self.assert_href(body)
+
 
 class TestResultGet(TestResultBase):
     def test_getOne(self):