summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--result_collection_api/resources/handlers.py228
-rw-r--r--result_collection_api/resources/pod_handlers.py17
-rw-r--r--result_collection_api/resources/project_handlers.py67
-rw-r--r--result_collection_api/resources/project_models.py2
-rw-r--r--result_collection_api/resources/testcase_handlers.py106
-rw-r--r--result_collection_api/resources/testcase_models.py16
-rw-r--r--result_collection_api/result_collection_api.py7
-rw-r--r--result_collection_api/tests/unit/test_base.py8
-rw-r--r--result_collection_api/tests/unit/test_result.py4
-rw-r--r--result_collection_api/tests/unit/test_testcase.py20
10 files changed, 239 insertions, 236 deletions
diff --git a/result_collection_api/resources/handlers.py b/result_collection_api/resources/handlers.py
index 3f9d842..7d2e816 100644
--- a/result_collection_api/resources/handlers.py
+++ b/result_collection_api/resources/handlers.py
@@ -24,7 +24,6 @@ from tornado import gen
from models import CreateResponse
from resources.result_models import TestResult
-from resources.testcase_models import Testcase
from common.constants import DEFAULT_REPRESENTATION, HTTP_BAD_REQUEST, \
HTTP_NOT_FOUND, HTTP_FORBIDDEN
from common.config import prepare_put_request
@@ -44,6 +43,10 @@ class GenericApiHandler(RequestHandler):
self.json_args = None
self.table = None
self.table_cls = None
+ self.db_projects = 'projects'
+ self.db_pods = 'pods'
+ self.db_testcases = 'testcases'
+ self.db_results = 'results'
def prepare(self):
if self.request.method != "GET" and self.request.method != "DELETE":
@@ -69,9 +72,15 @@ class GenericApiHandler(RequestHandler):
@asynchronous
@gen.coroutine
- def _create(self, error):
+ def _create(self, db_checks, **kwargs):
+ """
+ :param db_checks: [(table, exist, query, (error, message))]
+ :param db_op: (insert/remove)
+ :param res_op: (_create_response/None)
+ :return:
+ """
if self.json_args is None:
- raise HTTPError(HTTP_BAD_REQUEST, 'no body')
+ raise HTTPError(HTTP_BAD_REQUEST, "no body")
data = self.table_cls.from_dict(self.json_args)
name = data.name
@@ -79,11 +88,15 @@ class GenericApiHandler(RequestHandler):
raise HTTPError(HTTP_BAD_REQUEST,
'{} name missing'.format(self.table[:-1]))
- exist_data = yield self._eval_db(self.table, 'find_one',
- {"name": name})
- if exist_data is not None:
- raise HTTPError(HTTP_FORBIDDEN,
- error.format(name, self.table[:-1]))
+ for k, v in kwargs.iteritems():
+ data.__setattr__(k, v)
+
+ for table, exist, query, error in db_checks:
+ check = yield self._eval_db(table, 'find_one', query(data))
+ if (exist and not check) or (not exist and check):
+ code, message = error(data)
+ raise HTTPError(code, message)
+
data.creation_date = datetime.now()
yield self._eval_db(self.table, 'insert', data.format())
self.finish_request(self._create_response(name))
@@ -121,173 +134,68 @@ class GenericApiHandler(RequestHandler):
yield self._eval_db(self.table, 'remove', query)
self.finish_request()
- def _eval_db(self, table, method, param):
- return eval('self.db.%s.%s(param)' % (table, method))
-
-
-class VersionHandler(GenericApiHandler):
- """ Display a message for the API version """
- def get(self):
- self.finish_request([{'v1': 'basics'}])
-
-
-class TestcaseHandler(GenericApiHandler):
- """
- TestCasesHandler Class
- Handle the requests about the Test cases for test projects
- HTTP Methdods :
- - GET : Get all test cases and details about a specific one
- - POST : Add a test project
- - PUT : Edit test projects information (name and/or description)
- """
-
- def initialize(self):
- """ Prepares the database for the entire class """
- super(TestcaseHandler, self).initialize()
-
- @asynchronous
- @gen.coroutine
- def get(self, project_name, case_name=None):
- """
- Get testcases(s) info
- :param project_name:
- :param case_name:
- """
-
- query = {'project_name': project_name}
-
- if case_name is not None:
- query["name"] = case_name
- answer = yield self.db.testcases.find_one(query)
- if answer is None:
- raise HTTPError(HTTP_NOT_FOUND,
- "{} Not Exist".format(case_name))
- else:
- answer = format_data(answer, Testcase)
- else:
- res = []
- cursor = self.db.testcases.find(query)
- while (yield cursor.fetch_next):
- res.append(format_data(cursor.next_object(), Testcase))
- answer = {'testcases': res}
-
- self.finish_request(answer)
-
@asynchronous
@gen.coroutine
- def post(self, project_name):
- """ Create a test case"""
-
- if self.json_args is None:
- raise HTTPError(HTTP_BAD_REQUEST,
- "Check your request payload")
-
- # retrieve test project
- project = yield self.db.projects.find_one(
- {"name": project_name})
- if project is None:
- raise HTTPError(HTTP_FORBIDDEN,
- "Could not find project {}"
- .format(project_name))
-
- case_name = self.json_args.get('name')
- the_testcase = yield self.db.testcases.find_one(
- {"project_name": project_name, 'name': case_name})
- if the_testcase:
- raise HTTPError(HTTP_FORBIDDEN,
- "{} already exists as a case in project {}"
- .format(case_name, project_name))
-
- testcase = Testcase.from_dict(self.json_args)
- testcase.project_name = project_name
- testcase.creation_date = datetime.now()
-
- yield self.db.testcases.insert(testcase.format())
- self.finish_request(self._create_response(testcase.name))
-
- @asynchronous
- @gen.coroutine
- def put(self, project_name, case_name):
- """
- Updates the name and description of a test case
- :raises HTTPError (HTTP_NOT_FOUND, HTTP_FORBIDDEN)
- """
-
- query = {'project_name': project_name, 'name': case_name}
-
+ def _update(self, query, db_keys):
if self.json_args is None:
raise HTTPError(HTTP_BAD_REQUEST, "No payload")
- # check if there is a case for the project in url parameters
- from_testcase = yield self.db.testcases.find_one(query)
- if from_testcase is None:
+ # check old data exist
+ from_data = yield self._eval_db(self.table, 'find_one', query)
+ if from_data is None:
raise HTTPError(HTTP_NOT_FOUND,
- "{} could not be found as a {} case to be updated"
- .format(case_name, project_name))
-
- testcase = Testcase.from_dict(from_testcase)
- new_name = self.json_args.get("name")
- new_project_name = self.json_args.get("project_name")
- if not new_project_name:
- new_project_name = project_name
- new_description = self.json_args.get("description")
-
- # check if there is not an existing test case
- # with the name provided in the json payload
- if new_name != case_name or new_project_name != project_name:
- to_testcase = yield self.db.testcases.find_one(
- {'project_name': new_project_name, 'name': new_name})
- if to_testcase is not None:
- raise HTTPError(HTTP_FORBIDDEN,
- "{} already exists as a case in project"
- .format(new_name, new_project_name))
+ "{} could not be found in table [{}]"
+ .format(query, self.table))
- # new dict for changes
- request = dict()
- request = prepare_put_request(request,
- "name",
- new_name,
- testcase.name)
- request = prepare_put_request(request,
- "project_name",
- new_project_name,
- testcase.project_name)
- request = prepare_put_request(request,
- "description",
- new_description,
- testcase.description)
-
- # we raise an exception if there isn't a change
- if not request:
- raise HTTPError(HTTP_FORBIDDEN,
- "Nothing to update")
+ data = self.table_cls.from_dict(from_data)
+ # 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)
+ if to_data is not None:
+ raise HTTPError(HTTP_FORBIDDEN,
+ "{} already exists in table [{}]"
+ .format(new_query, self.table))
# we merge the whole document """
- edit_request = testcase.format()
- edit_request.update(request)
+ edit_request = data.format()
+ edit_request.update(self._update_request(data))
""" Updating the DB """
- yield self.db.testcases.update(query, edit_request)
- new_case = yield self.db.testcases.find_one({"_id": testcase._id})
- self.finish_request(format_data(new_case, Testcase))
+ yield self._eval_db(self.table, 'update', query, edit_request)
+ edit_request['_id'] = str(data._id)
+ self.finish_request(edit_request)
- @asynchronous
- @gen.coroutine
- def delete(self, project_name, case_name):
- """ Remove a test case"""
+ def _update_request(self, data):
+ request = dict()
+ for k, v in self.json_args.iteritems():
+ request = prepare_put_request(request, k, v,
+ data.__getattribute__(k))
+ if not request:
+ raise HTTPError(HTTP_FORBIDDEN, "Nothing to update")
+ return request
- query = {'project_name': project_name, 'name': case_name}
+ def _update_query(self, keys, data):
+ query = dict()
+ equal = True
+ for key in keys:
+ new = self.json_args.get(key)
+ old = data.__getattribute__(key)
+ if new is None:
+ new = old
+ elif new != old:
+ equal = False
+ query[key] = new
+ return equal, query
- # check for an existing case to be deleted
- testcase = yield self.db.testcases.find_one(query)
- if testcase is None:
- raise HTTPError(HTTP_NOT_FOUND,
- "{}/{} could not be found as a case to be deleted"
- .format(project_name, case_name))
+ def _eval_db(self, table, method, *args):
+ return eval('self.db.%s.%s(*args)' % (table, method))
- # just delete it, or maybe save it elsewhere in a future
- yield self.db.testcases.remove(query)
- self.finish_request()
+
+class VersionHandler(GenericApiHandler):
+ """ Display a message for the API version """
+ def get(self):
+ self.finish_request([{'v1': 'basics'}])
class TestResultsHandler(GenericApiHandler):
diff --git a/result_collection_api/resources/pod_handlers.py b/result_collection_api/resources/pod_handlers.py
index 590ae5b..c50ec51 100644
--- a/result_collection_api/resources/pod_handlers.py
+++ b/result_collection_api/resources/pod_handlers.py
@@ -1,9 +1,7 @@
-from tornado import gen
-from tornado.web import asynchronous
-
from tornado_swagger_ui.tornado_swagger import swagger
from handlers import GenericApiHandler
from pod_models import Pod
+from common.constants import HTTP_FORBIDDEN
class GenericPodHandler(GenericApiHandler):
@@ -23,7 +21,6 @@ class PodCLHandler(GenericPodHandler):
"""
self._list()
- @gen.coroutine
@swagger.operation(nickname='create')
def post(self):
"""
@@ -36,7 +33,15 @@ class PodCLHandler(GenericPodHandler):
@raise 403: pod already exists
@raise 400: post without body
"""
- self._create('{} already exists as a {}')
+ def query(data):
+ return {'name': data.name}
+
+ def error(data):
+ message = '{} already exists as a pod'.format(data.name)
+ return HTTP_FORBIDDEN, message
+
+ db_check = [(self.table, False, query, error)]
+ self._create(db_check)
class PodGURHandler(GenericPodHandler):
@@ -52,8 +57,6 @@ class PodGURHandler(GenericPodHandler):
query['name'] = pod_name
self._get_one(query)
- @asynchronous
- @gen.coroutine
def delete(self, pod_name):
""" Remove a POD
diff --git a/result_collection_api/resources/project_handlers.py b/result_collection_api/resources/project_handlers.py
index 69ce3b5..e56c01c 100644
--- a/result_collection_api/resources/project_handlers.py
+++ b/result_collection_api/resources/project_handlers.py
@@ -1,9 +1,6 @@
-from tornado import gen
-from tornado.web import HTTPError, asynchronous
-
from tornado_swagger_ui.tornado_swagger import swagger
-from handlers import GenericApiHandler, prepare_put_request, format_data
-from common.constants import HTTP_BAD_REQUEST, HTTP_FORBIDDEN, HTTP_NOT_FOUND
+from handlers import GenericApiHandler
+from common.constants import HTTP_FORBIDDEN
from project_models import Project
@@ -38,7 +35,15 @@ class ProjectCLHandler(GenericProjectHandler):
@raise 403: project already exists
@raise 400: post without body
"""
- self._create('{} already exists as a {}')
+ def query(data):
+ return {'name': data.name}
+
+ def error(data):
+ message = '{} already exists as a project'.format(data.name)
+ return HTTP_FORBIDDEN, message
+
+ db_check = [(self.table, False, query, error)]
+ self._create(db_check)
class ProjectGURHandler(GenericProjectHandler):
@@ -52,8 +57,6 @@ class ProjectGURHandler(GenericProjectHandler):
"""
self._get_one({'name': project_name})
- @asynchronous
- @gen.coroutine
@swagger.operation(nickname="update")
def put(self, project_name):
"""
@@ -66,53 +69,9 @@ class ProjectGURHandler(GenericProjectHandler):
@raise 404: project not exist
@raise 403: new project name already exist or nothing to update
"""
- if self.json_args is None:
- raise HTTPError(HTTP_BAD_REQUEST)
-
query = {'name': project_name}
- from_project = yield self.db.projects.find_one(query)
- if from_project is None:
- raise HTTPError(HTTP_NOT_FOUND,
- "{} could not be found".format(project_name))
-
- project = Project.from_dict(from_project)
- new_name = self.json_args.get("name")
- new_description = self.json_args.get("description")
-
- # check for payload name parameter in db
- # avoid a request if the project name has not changed in the payload
- if new_name != project.name:
- to_project = yield self.db.projects.find_one(
- {"name": new_name})
- if to_project is not None:
- raise HTTPError(HTTP_FORBIDDEN,
- "{} already exists as a project"
- .format(new_name))
-
- # new dict for changes
- request = dict()
- request = prepare_put_request(request,
- "name",
- new_name,
- project.name)
- request = prepare_put_request(request,
- "description",
- new_description,
- project.description)
-
- """ raise exception if there isn't a change """
- if not request:
- raise HTTPError(HTTP_FORBIDDEN, "Nothing to update")
-
- """ we merge the whole document """
- edit_request = project.format()
- edit_request.update(request)
-
- """ Updating the DB """
- yield self.db.projects.update(query, edit_request)
- new_project = yield self.db.projects.find_one({"_id": project._id})
-
- self.finish_request(format_data(new_project, Project))
+ db_keys = ['name']
+ self._update(query, db_keys)
@swagger.operation(nickname='delete')
def delete(self, project_name):
diff --git a/result_collection_api/resources/project_models.py b/result_collection_api/resources/project_models.py
index a8f8309..a1592c3 100644
--- a/result_collection_api/resources/project_models.py
+++ b/result_collection_api/resources/project_models.py
@@ -30,7 +30,7 @@ class ProjectUpdateRequest(object):
@swagger.model()
-class Project:
+class Project(object):
def __init__(self,
name=None, _id=None, description=None, create_date=None):
self._id = _id
diff --git a/result_collection_api/resources/testcase_handlers.py b/result_collection_api/resources/testcase_handlers.py
new file mode 100644
index 0000000..9c0eb63
--- /dev/null
+++ b/result_collection_api/resources/testcase_handlers.py
@@ -0,0 +1,106 @@
+from common.constants import HTTP_FORBIDDEN
+from resources.handlers import GenericApiHandler
+from resources.testcase_models import Testcase
+from tornado_swagger_ui.tornado_swagger import swagger
+
+
+class GenericTestcaseHandler(GenericApiHandler):
+ def __init__(self, application, request, **kwargs):
+ super(GenericTestcaseHandler, self).__init__(application,
+ request,
+ **kwargs)
+ self.table = self.db_testcases
+ self.table_cls = Testcase
+
+
+class TestcaseCLHandler(GenericTestcaseHandler):
+ @swagger.operation(nickname="list-all")
+ def get(self, project_name):
+ """
+ @description: list all testcases of a project by project_name
+ @return 200: return all testcases of this project,
+ empty list is no testcase exist in this project
+ @rtype: L{TestCases}
+ """
+ query = dict()
+ query['project_name'] = project_name
+ self._list(query)
+
+ @swagger.operation(nickname="create")
+ def post(self, project_name):
+ """
+ @description: create a testcase of a project by project_name
+ @param body: testcase to be created
+ @type body: L{TestcaseCreateRequest}
+ @in body: body
+ @rtype: L{Testcase}
+ @return 200: testcase is created in this project.
+ @raise 403: project not exist
+ or testcase already exists in this project
+ @raise 400: post without body
+ """
+ def p_query(data):
+ return {'name': data.project_name}
+
+ def tc_query(data):
+ return {
+ 'project_name': data.project_name,
+ 'name': data.name
+ }
+
+ def p_error(data):
+ message = 'Could not find project [{}]'.format(data.project_name)
+ return HTTP_FORBIDDEN, message
+
+ def tc_error(data):
+ message = '{} already exists as a testcase in project {}'\
+ .format(data.name, data.project_name)
+ return HTTP_FORBIDDEN, message
+
+ db_checks = [(self.db_projects, True, p_query, p_error),
+ (self.db_testcases, False, tc_query, tc_error)]
+ self._create(db_checks, project_name=project_name)
+
+
+class TestcaseGURHandler(GenericTestcaseHandler):
+ @swagger.operation(nickname='get-one')
+ def get(self, project_name, case_name):
+ """
+ @description: get a single testcase
+ by case_name and project_name
+ @rtype: L{Testcase}
+ @return 200: testcase exist
+ @raise 404: testcase not exist
+ """
+ query = dict()
+ query['project_name'] = project_name
+ query["name"] = case_name
+ self._get_one(query)
+
+ @swagger.operation(nickname="update")
+ def put(self, project_name, case_name):
+ """
+ @description: update a single testcase
+ by project_name and case_name
+ @param body: testcase to be updated
+ @type body: L{TestcaseUpdateRequest}
+ @in body: body
+ @rtype: L{Project}
+ @return 200: update success
+ @raise 404: testcase or project not exist
+ @raise 403: new testcase name already exist in project
+ or nothing to update
+ """
+ query = {'project_name': project_name, 'name': case_name}
+ db_keys = ['name', 'project_name']
+ self._update(query, db_keys)
+
+ @swagger.operation(nickname='delete')
+ def delete(self, project_name, case_name):
+ """
+ @description: delete a testcase by project_name and case_name
+ @return 200: delete success
+ @raise 404: testcase not exist
+ """
+ query = {'project_name': project_name, 'name': case_name}
+ self._delete(query)
diff --git a/result_collection_api/resources/testcase_models.py b/result_collection_api/resources/testcase_models.py
index a9ba41a..f386764 100644
--- a/result_collection_api/resources/testcase_models.py
+++ b/result_collection_api/resources/testcase_models.py
@@ -1,5 +1,11 @@
+from tornado_swagger_ui.tornado_swagger import swagger
+
+__author__ = '__serena__'
+
+
+@swagger.model()
class TestcaseCreateRequest(object):
- def __init__(self, url=None, name=None, description=None):
+ def __init__(self, name, url=None, description=None):
self.name = name
self.url = url
self.description = description
@@ -12,6 +18,7 @@ class TestcaseCreateRequest(object):
}
+@swagger.model()
class TestcaseUpdateRequest(object):
def __init__(self, name=None, description=None, project_name=None):
self.name = name
@@ -26,7 +33,8 @@ class TestcaseUpdateRequest(object):
}
-class Testcase:
+@swagger.model()
+class Testcase(object):
""" Describes a test case"""
def __init__(self):
@@ -73,7 +81,11 @@ class Testcase:
}
+@swagger.model()
class Testcases(object):
+ """
+ @ptype testcases: C{list} of L{Testcase}
+ """
def __init__(self, testcases=list()):
self.testcases = testcases
diff --git a/result_collection_api/result_collection_api.py b/result_collection_api/result_collection_api.py
index 344e0d7..25a670c 100644
--- a/result_collection_api/result_collection_api.py
+++ b/result_collection_api/result_collection_api.py
@@ -35,7 +35,8 @@ import tornado.ioloop
import motor
from resources.handlers import VersionHandler, \
- TestcaseHandler, TestResultsHandler, DashboardHandler
+ TestResultsHandler, DashboardHandler
+from resources.testcase_handlers import TestcaseCLHandler, TestcaseGURHandler
from resources.pod_handlers import PodCLHandler, PodGURHandler
from resources.project_handlers import ProjectCLHandler, ProjectGURHandler
from common.config import APIConfig
@@ -73,8 +74,8 @@ def make_app():
# few examples
# GET /projects/qtip/cases => Get cases for qtip
- (r"/api/v1/projects/([^/]+)/cases", TestcaseHandler),
- (r"/api/v1/projects/([^/]+)/cases/([^/]+)", TestcaseHandler),
+ (r"/api/v1/projects/([^/]+)/cases", TestcaseCLHandler),
+ (r"/api/v1/projects/([^/]+)/cases/([^/]+)", TestcaseGURHandler),
# new path to avoid a long depth
# GET /results?project=functest&case=keystone.catalog&pod=1
diff --git a/result_collection_api/tests/unit/test_base.py b/result_collection_api/tests/unit/test_base.py
index 44e42b7..dfb2070 100644
--- a/result_collection_api/tests/unit/test_base.py
+++ b/result_collection_api/tests/unit/test_base.py
@@ -5,7 +5,8 @@ from tornado.testing import AsyncHTTPTestCase
from resources.pod_handlers import PodCLHandler, PodGURHandler
from resources.project_handlers import ProjectCLHandler, ProjectGURHandler
from resources.handlers import VersionHandler, \
- TestcaseHandler, TestResultsHandler, DashboardHandler
+ TestResultsHandler, DashboardHandler
+from resources.testcase_handlers import TestcaseCLHandler, TestcaseGURHandler
from resources.models import CreateResponse
import fake_pymongo
@@ -32,8 +33,9 @@ class TestBase(AsyncHTTPTestCase):
(r"/api/v1/pods/([^/]+)", PodGURHandler),
(r"/api/v1/projects", ProjectCLHandler),
(r"/api/v1/projects/([^/]+)", ProjectGURHandler),
- (r"/api/v1/projects/([^/]+)/cases", TestcaseHandler),
- (r"/api/v1/projects/([^/]+)/cases/([^/]+)", TestcaseHandler),
+ (r"/api/v1/projects/([^/]+)/cases", TestcaseCLHandler),
+ (r"/api/v1/projects/([^/]+)/cases/([^/]+)",
+ TestcaseGURHandler),
(r"/api/v1/results", TestResultsHandler),
(r"/api/v1/results([^/]*)", TestResultsHandler),
(r"/api/v1/results/([^/]*)", TestResultsHandler),
diff --git a/result_collection_api/tests/unit/test_result.py b/result_collection_api/tests/unit/test_result.py
index 9c5093e..7dd07ef 100644
--- a/result_collection_api/tests/unit/test_result.py
+++ b/result_collection_api/tests/unit/test_result.py
@@ -70,8 +70,8 @@ class TestResultBase(TestBase):
self.basePath = '/api/v1/results'
self.req_pod = PodCreateRequest(self.pod, 'metal', 'zte pod 1')
self.req_project = ProjectCreateRequest(self.project, 'vping test')
- self.req_testcase = TestcaseCreateRequest('/cases/vping',
- self.case,
+ self.req_testcase = TestcaseCreateRequest(self.case,
+ '/cases/vping',
'vping-ssh test')
self.create_help('/api/v1/pods', self.req_pod)
self.create_help('/api/v1/projects', self.req_project)
diff --git a/result_collection_api/tests/unit/test_testcase.py b/result_collection_api/tests/unit/test_testcase.py
index 712a4e7..c6c0608 100644
--- a/result_collection_api/tests/unit/test_testcase.py
+++ b/result_collection_api/tests/unit/test_testcase.py
@@ -14,11 +14,11 @@ __author__ = '__serena__'
class TestCaseBase(TestBase):
def setUp(self):
super(TestCaseBase, self).setUp()
- self.req_d = TestcaseCreateRequest('/cases/vping_1',
- 'vping_1',
+ self.req_d = TestcaseCreateRequest('vping_1',
+ '/cases/vping_1',
'vping-ssh test')
- self.req_e = TestcaseCreateRequest('/cases/doctor_1',
- 'doctor_1',
+ self.req_e = TestcaseCreateRequest('doctor_1',
+ '/cases/doctor_1',
'create doctor')
self.update_d = TestcaseUpdateRequest('vping_1',
'vping-ssh test',
@@ -81,6 +81,18 @@ class TestCaseCreate(TestCaseBase):
self.assertEqual(code, HTTP_FORBIDDEN)
self.assertIn('Could not find project', body)
+ def test_emptyName(self):
+ req_empty = TestcaseCreateRequest('')
+ (code, body) = self.create(req_empty, self.project)
+ self.assertEqual(code, HTTP_BAD_REQUEST)
+ self.assertIn('testcase name missing', body)
+
+ def test_noneName(self):
+ req_none = TestcaseCreateRequest(None)
+ (code, body) = self.create(req_none, self.project)
+ self.assertEqual(code, HTTP_BAD_REQUEST)
+ self.assertIn('testcase name missing', body)
+
def test_success(self):
code, body = self.create_d()
self.assertEqual(code, HTTP_OK)