diff options
Diffstat (limited to 'utils/test/result_collection_api')
13 files changed, 503 insertions, 33 deletions
diff --git a/utils/test/result_collection_api/README.md b/utils/test/result_collection_api/README.md new file mode 100644 index 000000000..d73274c69 --- /dev/null +++ b/utils/test/result_collection_api/README.md @@ -0,0 +1,16 @@ +# result_collection_api + +## prepare: +Install: + +``` +pip install testtools +pip install discover +``` + +## How to: +run_test.sh: + +``` +bash ./run_test.sh +``` diff --git a/utils/test/result_collection_api/common/constants.py b/utils/test/result_collection_api/common/constants.py index 2c825c109..4d39a142d 100644 --- a/utils/test/result_collection_api/common/constants.py +++ b/utils/test/result_collection_api/common/constants.py @@ -12,3 +12,4 @@ DEFAULT_REPRESENTATION = "application/json" HTTP_BAD_REQUEST = 400 HTTP_FORBIDDEN = 403 HTTP_NOT_FOUND = 404 +HTTP_OK = 200 diff --git a/utils/test/result_collection_api/resources/handlers.py b/utils/test/result_collection_api/resources/handlers.py index c1e8eb182..fff166237 100644 --- a/utils/test/result_collection_api/resources/handlers.py +++ b/utils/test/result_collection_api/resources/handlers.py @@ -13,7 +13,8 @@ from tornado.web import RequestHandler, asynchronous, HTTPError from tornado import gen from datetime import datetime, timedelta -from models import Pod, TestProject, TestCase, TestResult +from models import TestProject, TestCase, TestResult +from resources.pod_models import Pod from common.constants import DEFAULT_REPRESENTATION, HTTP_BAD_REQUEST, \ HTTP_NOT_FOUND, HTTP_FORBIDDEN from common.config import prepare_put_request diff --git a/utils/test/result_collection_api/resources/models.py b/utils/test/result_collection_api/resources/models.py index 06e95f94f..adf6842c3 100644 --- a/utils/test/result_collection_api/resources/models.py +++ b/utils/test/result_collection_api/resources/models.py @@ -5,47 +5,41 @@ # 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 mv Pod to pod_models.py 6-18-2016
+# feng.xiaowei@zte.com.cn add MetaCreateResponse/MetaGetResponse 6-18-2016
##############################################################################
-class Pod:
- """ describes a POD platform """
- def __init__(self):
- self._id = ""
- self.name = ""
- self.creation_date = ""
- self.mode = ""
- self.details = ""
+class MetaCreateResponse(object):
+ def __init__(self, success=True, uri=''):
+ self.success = success
+ self.uri = uri
@staticmethod
- def pod_from_dict(pod_dict):
- if pod_dict is None:
+ def from_dict(meta_dict):
+ if meta_dict is None:
return None
- p = Pod()
- p._id = pod_dict.get('_id')
- p.creation_date = str(pod_dict.get('creation_date'))
- p.name = pod_dict.get('name')
- p.mode = pod_dict.get('mode')
- p.details = pod_dict.get('details')
- return p
+ meta = MetaCreateResponse()
+ meta.success = meta_dict.get('success')
+ meta.uri = meta_dict.get('uri')
+ return meta
- def format(self):
- return {
- "name": self.name,
- "mode": self.mode,
- "details": self.details,
- "creation_date": str(self.creation_date),
- }
- def format_http(self):
- return {
- "_id": str(self._id),
- "name": self.name,
- "mode": self.mode,
- "details": self.details,
- "creation_date": str(self.creation_date),
- }
+class MetaGetResponse(object):
+ def __init__(self, success=True, total=0):
+ self.success = success
+ self.total = total
+
+ @staticmethod
+ def from_dict(meta_dict):
+ if meta_dict is None:
+ return None
+
+ meta = MetaGetResponse()
+ meta.success = meta_dict.get('success')
+ meta.total = meta_dict.get('total')
+ return meta
class TestProject:
diff --git a/utils/test/result_collection_api/resources/pod_models.py b/utils/test/result_collection_api/resources/pod_models.py new file mode 100644 index 000000000..5c4ef7221 --- /dev/null +++ b/utils/test/result_collection_api/resources/pod_models.py @@ -0,0 +1,108 @@ +from models import MetaCreateResponse, MetaGetResponse + + +class PodCreateRequest(object): + def __init__(self, name='', mode='', details=''): + self.name = name + self.mode = mode + self.details = details + + def format(self): + return { + "name": self.name, + "mode": self.mode, + "details": self.details, + } + + @staticmethod + def from_dict(req_dict): + if req_dict is None: + return None + + req = PodCreateRequest() + req.name = req_dict.get('name') + req.mode = req_dict.get('mode') + req.details = req_dict.get('details') + return req + + +class Pod(PodCreateRequest): + """ describes a POD platform """ + def __init__(self, name='', mode='', details='', _id='', create_date=''): + super(Pod, self).__init__(name, mode, details) + self._id = _id + self.creation_date = create_date + + @staticmethod + def pod_from_dict(pod_dict): + if pod_dict is None: + return None + + p = Pod() + p._id = pod_dict.get('_id') + p.creation_date = str(pod_dict.get('creation_date')) + p.name = pod_dict.get('name') + p.mode = pod_dict.get('mode') + p.details = pod_dict.get('details') + return p + + def format(self): + f = super(Pod, self).format() + f['creation_date'] = str(self.creation_date) + return f + + def format_http(self): + f = self.format() + f['_id'] = str(self._id) + return f + + +class PodCreateResponse(object): + def __init__(self, pod=None, meta=None): + self.pod = pod + self.meta = meta + + @staticmethod + def from_dict(res_dict): + if res_dict is None: + return None + + res = PodCreateResponse() + res.pod = Pod.pod_from_dict(res_dict.get('pod')) + res.meta = MetaCreateResponse.from_dict(res_dict.get('meta')) + return res + + +class PodGetResponse(PodCreateRequest): + def __init__(self, name='', mode='', details='', create_date=''): + self.creation_date = create_date + super(PodGetResponse, self).__init__(name, mode, details) + + @staticmethod + def from_dict(req_dict): + if req_dict is None: + return None + + res = PodGetResponse() + res.creation_date = str(req_dict.get('creation_date')) + res.name = req_dict.get('name') + res.mode = req_dict.get('mode') + res.details = req_dict.get('details') + return res + + +class PodsGetResponse(object): + def __init__(self, pods=[], meta=None): + self.pods = pods + self.meta = meta + + @staticmethod + def from_dict(res_dict): + if res_dict is None: + return None + + res = PodsGetResponse() + for pod in res_dict.get('pods'): + res.pods.append(PodGetResponse.from_dict(pod)) + res.meta = MetaGetResponse.from_dict(res_dict.get('meta')) + return res diff --git a/utils/test/result_collection_api/run_test.sh b/utils/test/result_collection_api/run_test.sh new file mode 100755 index 000000000..6006fcf8b --- /dev/null +++ b/utils/test/result_collection_api/run_test.sh @@ -0,0 +1,10 @@ +#! /bin/bash + +# Before run this script, make sure that testtools and discover +# had been installed in your env +# or else using pip to install them as follows: +# pip install testtools, discover + +find . -type f -name "*.pyc" -delete +testrargs="discover ./tests/unit" +python -m testtools.run $testrargs
\ No newline at end of file diff --git a/utils/test/result_collection_api/tests/__init__.py b/utils/test/result_collection_api/tests/__init__.py new file mode 100644 index 000000000..3ed9fd0f3 --- /dev/null +++ b/utils/test/result_collection_api/tests/__init__.py @@ -0,0 +1 @@ +__author__ = 'root' diff --git a/utils/test/result_collection_api/tests/unit/__init__.py b/utils/test/result_collection_api/tests/unit/__init__.py new file mode 100644 index 000000000..3ed9fd0f3 --- /dev/null +++ b/utils/test/result_collection_api/tests/unit/__init__.py @@ -0,0 +1 @@ +__author__ = 'root' diff --git a/utils/test/result_collection_api/tests/unit/fake_pymongo.py b/utils/test/result_collection_api/tests/unit/fake_pymongo.py new file mode 100644 index 000000000..e5ded376e --- /dev/null +++ b/utils/test/result_collection_api/tests/unit/fake_pymongo.py @@ -0,0 +1,132 @@ +from bson.objectid import ObjectId +from concurrent.futures import ThreadPoolExecutor + +__author__ = 'serena' + + +class MemCursor(object): + def __init__(self, collection): + self.collection = collection + self.count = len(self.collection) + + def _is_next_exist(self): + return self.count != 0 + + @property + def fetch_next(self): + with ThreadPoolExecutor(max_workers=2) as executor: + result = executor.submit(self._is_next_exist) + return result + + def next_object(self): + self.count -= 1 + return self.collection.pop() + + +class MemDb(object): + + def __init__(self): + self.contents = [] + pass + + def _find_one(self, spec_or_id=None, *args): + if spec_or_id is not None and not isinstance(spec_or_id, dict): + spec_or_id = {"_id": spec_or_id} + cursor = self._find(spec_or_id, *args) + for result in cursor: + return result + return None + + def find_one(self, spec_or_id=None, *args): + with ThreadPoolExecutor(max_workers=2) as executor: + result = executor.submit(self._find_one, spec_or_id, *args) + return result + + def _insert(self, doc_or_docs): + + docs = doc_or_docs + return_one = False + if isinstance(docs, dict): + return_one = True + docs = [docs] + + ids = [] + for doc in docs: + if '_id' not in doc: + doc['_id'] = ObjectId() + if not self._find_one(doc['_id']): + ids.append(doc['_id']) + self.contents.append(doc_or_docs) + + if len(ids) == 0: + return None + if return_one: + return ids[0] + else: + return ids + + def insert(self, doc_or_docs): + with ThreadPoolExecutor(max_workers=2) as executor: + result = executor.submit(self._insert, doc_or_docs) + return result + + @staticmethod + def _in(content, *args): + for arg in args: + for k, v in arg.iteritems(): + if content.get(k, None) != v: + return False + + return True + + def _find(self, *args): + res = [] + for content in self.contents: + if self._in(content, *args): + res.append(content) + + return res + + def find(self, *args): + return MemCursor(self._find(*args)) + + def _update(self, spec, document): + updated = False + for index in range(len(self.contents)): + content = self.contents[index] + if self._in(content, spec): + for k, v in document.iteritems(): + updated = True + content[k] = v + self.contents[index] = content + return updated + + def update(self, spec, document): + with ThreadPoolExecutor(max_workers=2) as executor: + result = executor.submit(self._update, spec, document) + return result + + def _remove(self, spec_or_id=None): + if spec_or_id is None: + self.contents = [] + if not isinstance(spec_or_id, dict): + spec_or_id = {'_id': spec_or_id} + for index in range(len(self.contents)): + content = self.contents[index] + if self._in(content, spec_or_id): + del self.contents[index] + return True + return False + + def remove(self, spec_or_id=None): + with ThreadPoolExecutor(max_workers=2) as executor: + result = executor.submit(self._remove, spec_or_id) + return result + + def clear(self): + self._remove() + +pod = MemDb() +test_projects = MemDb() +test_cases = MemDb() +test_results = MemDb() diff --git a/utils/test/result_collection_api/tests/unit/test_base.py b/utils/test/result_collection_api/tests/unit/test_base.py new file mode 100644 index 000000000..98190fb94 --- /dev/null +++ b/utils/test/result_collection_api/tests/unit/test_base.py @@ -0,0 +1,54 @@ +import json +from tornado.web import Application +from tornado.testing import AsyncHTTPTestCase + +from resources.handlers import VersionHandler, PodHandler, \ + TestProjectHandler, TestCasesHandler, TestResultsHandler, DashboardHandler +import fake_pymongo + + +class TestBase(AsyncHTTPTestCase): + headers = {'Content-Type': 'application/json; charset=UTF-8'} + + def setUp(self): + self.addCleanup(self._clear) + super(TestBase, self).setUp() + + def get_app(self): + return Application( + [ + (r"/version", VersionHandler), + (r"/pods", PodHandler), + (r"/pods/([^/]+)", PodHandler), + (r"/test_projects", TestProjectHandler), + (r"/test_projects/([^/]+)", TestProjectHandler), + (r"/test_projects/([^/]+)/cases", TestCasesHandler), + (r"/test_projects/([^/]+)/cases/([^/]+)", TestCasesHandler), + (r"/results", TestResultsHandler), + (r"/results([^/]*)", TestResultsHandler), + (r"/results/([^/]*)", TestResultsHandler), + (r"/dashboard", DashboardHandler), + (r"/dashboard([^/]*)", DashboardHandler), + (r"/dashboard/([^/]*)", DashboardHandler), + ], + db=fake_pymongo, + debug=True, + ) + + def create(self, uri, body=None): + return self.fetch(uri, + method='POST', + body=json.dumps(body), + headers=self.headers) + + def get(self, uri): + return self.fetch(uri, + method='GET', + headers=self.headers) + + @staticmethod + def _clear(): + fake_pymongo.pod.clear() + fake_pymongo.test_projects.clear() + fake_pymongo.test_cases.clear() + fake_pymongo.test_results.clear() diff --git a/utils/test/result_collection_api/tests/unit/test_fake_pymongo.py b/utils/test/result_collection_api/tests/unit/test_fake_pymongo.py new file mode 100644 index 000000000..5ddbf28d9 --- /dev/null +++ b/utils/test/result_collection_api/tests/unit/test_fake_pymongo.py @@ -0,0 +1,52 @@ +import unittest +from tornado.web import Application +from tornado import gen +from tornado.testing import AsyncHTTPTestCase, gen_test + +import fake_pymongo + + +class MyTest(AsyncHTTPTestCase): + def setUp(self): + super(MyTest, self).setUp() + self.db = fake_pymongo + self.io_loop.run_sync(self.fixture_setup) + + def get_app(self): + return Application() + + @gen.coroutine + def fixture_setup(self): + self.test1 = {'_id': '1', 'name': 'test1'} + self.test2 = {'name': 'test2'} + yield self.db.pod.insert({'_id': '1', 'name': 'test1'}) + yield self.db.pod.insert({'name': 'test2'}) + + @gen_test + def test_find_one(self): + user = yield self.db.pod.find_one({'name': 'test1'}) + self.assertEqual(user, self.test1) + + @gen_test + def test_find(self): + cursor = self.db.pod.find() + names = [] + while (yield cursor.fetch_next): + ob = cursor.next_object() + names.append(ob.get('name')) + self.assertItemsEqual(names, ['test1', 'test2']) + + @gen_test + def test_update(self): + yield self.db.pod.update({'_id': '1'}, {'name': 'new_test1'}) + user = yield self.db.pod.find_one({'_id': '1'}) + self.assertEqual(user.get('name', None), 'new_test1') + + @gen_test + def test_remove(self): + yield self.db.pod.remove({'_id': '1'}) + user = yield self.db.pod.find_one({'_id': '1'}) + self.assertIsNone(user) + +if __name__ == '__main__': + unittest.main() diff --git a/utils/test/result_collection_api/tests/unit/test_pod.py b/utils/test/result_collection_api/tests/unit/test_pod.py new file mode 100644 index 000000000..5a3d485ab --- /dev/null +++ b/utils/test/result_collection_api/tests/unit/test_pod.py @@ -0,0 +1,86 @@ +import unittest +import json + +from test_base import TestBase +from resources.pod_models import PodCreateRequest, \ + PodCreateResponse, PodsGetResponse +from common.constants import HTTP_OK, HTTP_BAD_REQUEST, HTTP_FORBIDDEN + + +class TestPodCreate(TestBase): + req = PodCreateRequest(name='zte-1', mode='alive', details='zte pod 1') + + def test_withoutBody(self): + res = self.create('/pods', body=None) + self.assertEqual(res.code, HTTP_BAD_REQUEST) + + def test_success(self): + res = self.create('/pods', body=self.req.format()) + self.assertEqual(res.code, HTTP_OK) + res_body = PodCreateResponse.from_dict(json.loads(res.body)) + self._assertMeta(res_body.meta, True) + self._assertBody(res_body.pod) + + def test_alreadyExist(self): + self.create('/pods', body=self.req.format()) + res = self.create('/pods', body=self.req.format()) + self.assertEqual(res.code, HTTP_FORBIDDEN) + self.assertIn('already exists', res.body) + + def _assertMeta(self, meta, success): + self.assertEqual(meta.success, success) + if success: + self.assertEqual(meta.uri, '/pods/{}'.format(self.req.name)) + + def _assertBody(self, res): + self.assertEqual(res.name, self.req.name) + self.assertEqual(res.mode, self.req.mode) + self.assertEqual(res.details, self.req.details) + self.assertIsNotNone(res.creation_date) + self.assertIsNotNone(res._id) + + +class TestPodGet(TestBase): + def test_notExist(self): + res = self.get('/pods/notExist') + body = PodsGetResponse.from_dict(json.loads(res.body)) + self._assertMeta(body.meta, 0) + + def test_getOne(self): + self.create('/pods', body=TestPodCreate.req.format()) + res = self.get('/pods/{}'.format(TestPodCreate.req.name)) + body = PodsGetResponse.from_dict(json.loads(res.body)) + self._assertMeta(body.meta, 1) + self._assertBody(TestPodCreate.req, body.pods[0]) + + def test_list(self): + req = PodCreateRequest(name='zte-2', mode='alive', details='zte pod 2') + self.create('/pods', body=TestPodCreate.req.format()) + self.create('/pods', body=req.format()) + res = self.get('/pods') + body = PodsGetResponse.from_dict(json.loads(res.body)) + self._assertMeta(body.meta, 2) + for pod in body.pods: + if req.name == pod.name: + self._assertBody(req, pod) + else: + self._assertBody(TestPodCreate.req, pod) + + def _assertMeta(self, meta, total): + def check_success(): + if total is 0: + return False + else: + return True + self.assertEqual(meta.total, total) + self.assertEqual(meta.success, check_success()) + + def _assertBody(self, req, res): + self.assertEqual(res.name, req.name) + self.assertEqual(res.mode, req.mode) + self.assertEqual(res.details, req.details) + self.assertIsNotNone(res.creation_date) + + +if __name__ == '__main__': + unittest.main() diff --git a/utils/test/result_collection_api/tests/unit/test_version.py b/utils/test/result_collection_api/tests/unit/test_version.py new file mode 100644 index 000000000..918f2f052 --- /dev/null +++ b/utils/test/result_collection_api/tests/unit/test_version.py @@ -0,0 +1,14 @@ +import unittest + +from test_base import TestBase + +__author__ = 'serena' + + +class TestVersion(TestBase): + def test_get_version(self): + response = self.fetch('/version') + self.assertEqual(response.code, 200) + +if __name__ == '__main__': + unittest.main() |