Implements integration testing framework

- reusing functional tests for integration purposes
 - common parts of both test frameworks were extracted to tests/common
 - tox.ini updated
 - README updated
 - test_regression.sh updated to run regression
   checks on both integration and functional
This commit is contained in:
Denis Makogon 2016-11-19 04:06:24 +02:00
parent d5df8430b9
commit fd43c0f157
16 changed files with 517 additions and 178 deletions

View File

@ -61,10 +61,6 @@ Install dependencies:
$ pip install -r requirements.txt -r test-requirements.txt
Install `functions_python` lib:
$ pip install -e git+ssh://git@github.com/iron-io/functions_python.git#egg=functions-python
Install LaOS itself:
$ pip install -e .
@ -191,8 +187,70 @@ Cons:
Testing: Integration
--------------------
TBD
Integration tests are dependent on following env variables:
* TEST_DB_URI - similar to functional tests, database endpoint
* FUNCTIONS_HOST - IronFunctions API host
* FUNCTIONS_PORT - IronFunctions API port
* FUNCTIONS_API_PROTO - IronFunctions API protocol
* FUNCTIONS_API_VERSION - IronFunctions API version
* OS_AUTH_URL - OpenStack Identity endpoint
* OS_PROJECT_ID - OpenStack user-specific project ID
* OS_TOKEN - OpenStack user project-bound auth token
How to get token? - Set env variables:
* OS_USERNAME
* OS_PASSWORD
* OS_PROJECT_NAME
and run following command:
echo -e "{
\"auth\": {
\"identity\": {
\"methods\": [\"password\"],
\"password\": {
\"user\": {
\"name\": \"${OS_USERNAME:-admin}\",
\"domain\": { \"id\": \"${OS_DOMAIN:-default}\" },
\"password\": \"${OS_PASSWORD:-root}\"
}
}
},
\"scope\": {
\"project\": {
\"name\": \"${OS_PROJECT_NAME:-admin}\",
\"domain\": {\"id\": \"${OS_DOMAIN:-default}\" }
}
}
}
}" >> token_request.json
After that:
export OS_TOKEN=`curl -si -d @token_request.json -H "Content-type: application/json" ${OS_AUTH_URL}/auth/tokens | awk '/X-Subject-Token/ {print $2}'`
If variable remains empty, please check your authentication parameters specified in `token_request.json`.
How to get project ID? - Use following command
export RAW_PrID=`curl -si -d @token_request.json -H "Content-type: application/json" ${OS_AUTH_URL}/auth/tokens | grep Default | awk '{print $20}'`
export OS_PROJECT_ID=${RAW_PrID:1:-2}
If variable remains empty, please check your authentication parameters specified in `token_request.json`.
To run tests use following command:
export TEST_DB_URI=mysql://<your-user>:<your-user-password>@<mysql-host>:<mysql-port>/<functions-db>
export FUNCTIONS_HOST=<functions-host>
export FUNCTIONS_PORT=<functions-port>
export FUNCTIONS_API_PROTO=<functions-api-protocol>
export FUNCTIONS_API_VERSION=<functions-api-version>
export OS_AUTH_URL=<openstack-idenitity-url>
export OS_PROJECT_ID=<project-id>
export OS_TOKEN=<project-bound-auth-token>
tox -epy35-integration
Testing: Coverage regression
----------------------------

View File

@ -210,7 +210,8 @@ class AppV1Controller(controllers.ServiceControllerBase):
if fn_app_routes:
return web.json_response(data={
"error": {
"message": ("Unable to delete app {} with routes".format(app))
"message": ("Unable to delete app {} "
"with routes".format(app))
}
}, status=403)

View File

84
laos/tests/common/apps.py Normal file
View File

@ -0,0 +1,84 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
class AppsTestSuite(object):
def list_apps(self):
json, http_status = self.testloop.run_until_complete(
self.test_client.apps.list())
self.assertIn("message", json)
self.assertIn("apps", json)
self.assertEqual(200, http_status)
def get_unknown(self):
json, http_status = self.testloop.run_until_complete(
self.test_client.apps.show("unknown"))
self.assertEqual(404, http_status)
self.assertIn("error", json)
def create_and_delete(self):
create_json, create_status = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
delete_json, delete_status = self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertIn("message", create_json)
self.assertIn("app", create_json)
self.assertEqual(200, create_status)
self.assertIn("message", delete_json)
self.assertEqual(200, delete_status)
def attempt_to_double_create(self):
app = "testapp"
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create(app))
err, status = self.testloop.run_until_complete(
self.test_client.apps.create(app))
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(409, status)
self.assertIn("error", err)
self.assertIn("message", err["error"])
def attempt_delete_unknonw(self):
json, http_status = self.testloop.run_until_complete(
self.test_client.apps.delete("unknown"))
self.assertEqual(404, http_status)
self.assertIn("error", json)
def delete_with_routes(self):
app_name = "testapp"
app, _ = self.testloop.run_until_complete(
self.test_client.apps.create(app_name))
self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
attempt, status = self.testloop.run_until_complete(
self.test_client.apps.delete(app["app"]["name"])
)
self.testloop.run_until_complete(
self.test_client.routes.delete(
app["app"]["name"], self.route_data["path"])
)
_, status_2 = self.testloop.run_until_complete(
self.test_client.apps.delete(app["app"]["name"])
)
self.assertEqual(403, status)
self.assertIn("error", attempt)
self.assertIn("message", attempt["error"])
self.assertIn("with routes", attempt["error"]["message"])
self.assertEqual(200, status_2)

42
laos/tests/common/base.py Normal file
View File

@ -0,0 +1,42 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import asyncio
import datetime
import uvloop
from laos.common import logger as log
class LaosTestsBase(object):
def get_loop_and_logger(self, test_type):
self.route_data = {
"type": "sync",
"path": "/hello-sync-private",
"image": "iron/hello",
"is_public": "false"
}
try:
testloop = asyncio.get_event_loop()
except Exception:
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
testloop = asyncio.get_event_loop()
logger = log.UnifiedLogger(
log_to_console=False,
filename=("/tmp/laos-{}-tests-run-{}.log"
.format(test_type, datetime.datetime.now())),
level="DEBUG").setup_logger(__package__)
return testloop, logger

View File

@ -74,12 +74,15 @@ class RoutesV1(object):
class ProjectBoundLaosTestClient(test_utils.TestClient):
def __init__(self, app_or_server, project_id):
def __init__(self, app_or_server, project_id, **kwargs):
super(ProjectBoundLaosTestClient, self).__init__(app_or_server)
self.project_id = project_id
self.headers = {
"Content-Type": "application/json"
}
if kwargs.get("headers"):
self.headers.update(kwargs.get("headers"))
self.apps = AppsV1(self)
self.routes = RoutesV1(self)

118
laos/tests/common/routes.py Normal file
View File

@ -0,0 +1,118 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json as jsonlib
class AppRoutesTestSuite(object):
def list_routes_from_unknown_app(self):
json, status = self.testloop.run_until_complete(
self.test_client.routes.list("uknown_app")
)
self.assertEqual(status, 404)
self.assertIn("error", json)
self.assertIn("not found", json["error"]["message"])
def list_routes_from_existing_app(self):
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
json, status = self.testloop.run_until_complete(
self.test_client.routes.list(create_json["app"]["name"])
)
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(status, 200)
self.assertIn("routes", json)
self.assertIn("message", json)
def show_unknown_route_from_existing_app(self):
path = "/unknown_path"
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
json, status = self.testloop.run_until_complete(
self.test_client.routes.show(
create_json["app"]["name"], path)
)
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(404, status)
self.assertIn("error", json)
self.assertIn("not found", json["error"]["message"])
def delete_unknown_route_from_existing_app(self):
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
json, status = self.testloop.run_until_complete(
self.test_client.routes.delete(
create_json["app"]["name"], "/unknown_path")
)
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(404, status)
self.assertIn("error", json)
self.assertIn("not found", json["error"]["message"])
def create_and_delete_route(self):
app, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
route, create_status = self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
route_deleted, delete_status = self.testloop.run_until_complete(
self.test_client.routes.delete(
app["app"]["name"], self.route_data["path"])
)
self.testloop.run_until_complete(
self.test_client.apps.delete(app["app"]["name"]))
after_post = route["route"]
for k in self.route_data:
if k == "path":
self.assertIn(self.route_data["path"], after_post[k])
continue
if k == "is_public":
is_public = jsonlib.loads(self.route_data[k])
self.assertEqual(is_public, after_post[k])
continue
self.assertEqual(self.route_data[k], after_post[k])
self.assertEqual(200, delete_status)
self.assertEqual(200, create_status)
self.assertIn("message", route_deleted)
def double_create_route(self):
app, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
json, double_create_status = self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
self.testloop.run_until_complete(
self.test_client.routes.delete(
app["app"]["name"], self.route_data["path"])
)
self.testloop.run_until_complete(
self.test_client.apps.delete(app["app"]["name"]))
self.assertEqual(409, double_create_status)
self.assertIn("error", json)
self.assertIn("message", json["error"])
self.assertIn("already exist", json["error"]["message"])

View File

@ -12,13 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import asyncio
import collections
import datetime
import os
import testtools
import uuid
import uvloop
from laos.api.controllers import apps
from laos.api.controllers import routes
@ -28,27 +25,16 @@ from laos.api.middleware import content_type
from laos.common.base import service
from laos.common import config
from laos.common import logger as log
from laos.tests.common import base
from laos.tests.common import client
from laos.tests.fakes import functions_api
from laos.tests.functional import client
class LaosFunctionalTestsBase(testtools.TestCase):
class LaosFunctionalTestsBase(base.LaosTestsBase, testtools.TestCase):
def setUp(self):
try:
self.testloop = asyncio.get_event_loop()
except Exception:
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
self.testloop = asyncio.get_event_loop()
logger = log.UnifiedLogger(
log_to_console=False,
filename=("/tmp/laos-integration-tests-run-{}.log"
.format(datetime.datetime.now())),
level="DEBUG").setup_logger(__package__)
self.testloop, logger = self.get_loop_and_logger("functional")
self.testapp = service.AbstractWebServer(
host="localhost",

View File

@ -12,71 +12,26 @@
# License for the specific language governing permissions and limitations
# under the License.
from laos.tests.common import apps as apps_suite
from laos.tests.functional import base
class TestApps(base.LaosFunctionalTestsBase):
class TestApps(base.LaosFunctionalTestsBase, apps_suite.AppsTestSuite):
def test_list_apps(self):
json, http_status = self.testloop.run_until_complete(
self.test_client.apps.list())
self.assertIn("message", json)
self.assertIn("apps", json)
self.assertEqual(200, http_status)
super(TestApps, self).list_apps()
def test_get_unknown(self):
json, http_status = self.testloop.run_until_complete(
self.test_client.apps.show("unknown"))
self.assertEqual(404, http_status)
self.assertIn("error", json)
super(TestApps, self).get_unknown()
def test_create_and_delete(self):
create_json, create_status = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
delete_json, delete_status = self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertIn("message", create_json)
self.assertIn("app", create_json)
self.assertEqual(200, create_status)
self.assertIn("message", delete_json)
self.assertEqual(200, delete_status)
super(TestApps, self).create_and_delete()
def test_attempt_to_double_create(self):
app = "testapp"
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create(app))
err, status = self.testloop.run_until_complete(
self.test_client.apps.create(app))
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(409, status)
self.assertIn("error", err)
self.assertIn("message", err["error"])
super(TestApps, self).attempt_to_double_create()
def test_attempt_delete_unknonw(self):
json, http_status = self.testloop.run_until_complete(
self.test_client.apps.delete("unknown"))
self.assertEqual(404, http_status)
self.assertIn("error", json)
super(TestApps, self).attempt_delete_unknonw()
def test_delete_with_routes(self):
app_name = "testapp"
app, _ = self.testloop.run_until_complete(
self.test_client.apps.create(app_name))
self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
attempt, status = self.testloop.run_until_complete(
self.test_client.apps.delete(app["app"]["name"])
)
self.testloop.run_until_complete(
self.test_client.routes.delete(
app["app"]["name"], self.route_data["path"])
)
self.assertEqual(403, status)
self.assertIn("error", attempt)
self.assertIn("message", attempt["error"])
self.assertIn("has routes", attempt["error"]["message"])
super(TestApps, self).delete_with_routes()

View File

@ -12,110 +12,31 @@
# License for the specific language governing permissions and limitations
# under the License.
import json as jsonlib
from laos.tests.common import routes as routes_suite
from laos.tests.functional import base
class TestAppRoutes(base.LaosFunctionalTestsBase):
class TestAppRoutes(base.LaosFunctionalTestsBase,
routes_suite.AppRoutesTestSuite):
def test_list_routes_from_unknown_app(self):
json, status = self.testloop.run_until_complete(
self.test_client.routes.list("uknown_app")
)
self.assertEqual(status, 404)
self.assertIn("error", json)
self.assertIn("not found", json["error"]["message"])
super(TestAppRoutes, self).list_routes_from_unknown_app()
def test_list_routes_from_existing_app(self):
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
json, status = self.testloop.run_until_complete(
self.test_client.routes.list(create_json["app"]["name"])
)
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(status, 200)
self.assertIn("routes", json)
self.assertIn("message", json)
super(TestAppRoutes, self).list_routes_from_existing_app()
def test_show_unknown_route_from_existing_app(self):
path = "/unknown_path"
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
json, status = self.testloop.run_until_complete(
self.test_client.routes.show(
create_json["app"]["name"], path)
)
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(404, status)
self.assertIn("error", json)
self.assertIn("not found", json["error"]["message"])
self.assertIn(path[1:], json["error"]["message"])
super(
TestAppRoutes, self
).show_unknown_route_from_existing_app()
def test_delete_unknown_route_from_existing_app(self):
create_json, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
json, status = self.testloop.run_until_complete(
self.test_client.routes.delete(
create_json["app"]["name"], "/unknown_path")
)
self.testloop.run_until_complete(
self.test_client.apps.delete(create_json["app"]["name"]))
self.assertEqual(404, status)
self.assertIn("error", json)
self.assertIn("not found", json["error"]["message"])
super(
TestAppRoutes, self
).delete_unknown_route_from_existing_app()
def test_create_and_delete_route(self):
app, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
route, create_status = self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
route_deleted, delete_status = self.testloop.run_until_complete(
self.test_client.routes.delete(
app["app"]["name"], self.route_data["path"])
)
self.testloop.run_until_complete(
self.test_client.apps.delete(app["app"]["name"]))
after_post = route["route"]
for k in self.route_data:
if k == "path":
self.assertIn(self.route_data["path"], after_post[k])
continue
if k == "is_public":
is_public = jsonlib.loads(self.route_data[k])
self.assertEqual(is_public, after_post[k])
continue
self.assertEqual(self.route_data[k], after_post[k])
self.assertEqual(200, delete_status)
self.assertEqual(200, create_status)
self.assertIn("message", route_deleted)
super(TestAppRoutes, self).create_and_delete_route()
def test_double_create_route(self):
app, _ = self.testloop.run_until_complete(
self.test_client.apps.create("testapp"))
self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
json, double_create_status = self.testloop.run_until_complete(
self.test_client.routes.create(
app["app"]["name"], **self.route_data)
)
self.testloop.run_until_complete(
self.test_client.routes.delete(
app["app"]["name"], self.route_data["path"])
)
self.testloop.run_until_complete(
self.test_client.apps.delete(app["app"]["name"]))
self.assertEqual(409, double_create_status)
self.assertIn("error", json)
self.assertIn("message", json["error"])
self.assertIn("already exist", json["error"]["message"])
super(TestAppRoutes, self).double_create_route()

View File

View File

@ -0,0 +1,72 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import testtools
from laos.common import config
from laos.service import laos_api
from laos.tests.common import base
from laos.tests.common import client
class LaosIntegrationTestsBase(base.LaosTestsBase, testtools.TestCase):
def setUp(self):
self.testloop, logger = self.get_loop_and_logger("integration")
(functions_host, functions_port,
functions_api_protocol,
functions_api_version, db_uri,
keystone_endpoint, project_id, os_token) = (
os.getenv("FUNCTIONS_HOST"), os.getenv("FUNCTIONS_PORT", 8080),
os.getenv("FUNCTIONS_API_PROTO", "http"),
os.getenv("FUNCTIONS_API_VERSION", "v1"), os.getenv("TEST_DB_URI"),
os.getenv("OS_AUTH_URL"), os.getenv("OS_PROJECT_ID"),
os.getenv("OS_TOKEN"),
)
fnclient = config.FunctionsClient(
functions_host,
api_port=functions_port,
api_protocol=functions_api_protocol,
api_version=functions_api_version,
)
self.testloop.run_until_complete(fnclient.ping(loop=self.testloop))
connection_pool = config.Connection(db_uri, loop=self.testloop)
config.Config(
auth_url=keystone_endpoint,
functions_client=fnclient,
logger=logger,
connection=connection_pool,
event_loop=self.testloop,
)
self.test_app = laos_api.API(
loop=self.testloop, logger=logger, debug=True)
self.test_client = client.ProjectBoundLaosTestClient(
self.test_app.root_service, project_id, headers={
"X-Auth-Token": os_token
})
self.testloop.run_until_complete(
self.test_client.start_server())
super(LaosIntegrationTestsBase, self).setUp()
def tearDown(self):
self.testloop.run_until_complete(self.test_client.close())
super(LaosIntegrationTestsBase, self).tearDown()

View File

@ -0,0 +1,38 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from laos.tests.common import apps as apps_suite
from laos.tests.integration import base
class TestIntegrationApps(base.LaosIntegrationTestsBase,
apps_suite.AppsTestSuite):
def test_list_apps(self):
super(TestIntegrationApps, self).list_apps()
def test_get_unknown(self):
super(TestIntegrationApps, self).get_unknown()
def test_create_and_delete(self):
super(TestIntegrationApps, self).create_and_delete()
def test_attempt_to_double_create(self):
super(TestIntegrationApps, self).attempt_to_double_create()
def test_attempt_delete_unknonw(self):
super(TestIntegrationApps, self).attempt_delete_unknonw()
def test_delete_with_routes(self):
super(TestIntegrationApps, self).delete_with_routes()

View File

@ -0,0 +1,50 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from laos.tests.common import routes as routes_suite
from laos.tests.functional import base
class TestIntegrationAppRoutes(base.LaosFunctionalTestsBase,
routes_suite.AppRoutesTestSuite):
def test_list_routes_from_unknown_app(self):
super(
TestIntegrationAppRoutes, self
).list_routes_from_unknown_app()
def test_list_routes_from_existing_app(self):
super(
TestIntegrationAppRoutes, self
).list_routes_from_existing_app()
def test_show_unknown_route_from_existing_app(self):
super(
TestIntegrationAppRoutes, self
).show_unknown_route_from_existing_app()
def test_delete_unknown_route_from_existing_app(self):
super(
TestIntegrationAppRoutes, self
).delete_unknown_route_from_existing_app()
def test_create_and_delete_route(self):
super(
TestIntegrationAppRoutes, self
).create_and_delete_route()
def test_double_create_route(self):
super(
TestIntegrationAppRoutes, self
).double_create_route()

View File

@ -4,17 +4,17 @@ set +x
set +e
function get_current_coverage {
local prev_stat_raw=`TEST_DB_URI=${TEST_DB_URI} pytest --tb=long --capture=sys --cov=laos --capture=fd laos/tests/functional | grep TOTAL | awk '{print $4}'`
local prev_stat_raw=`pytest --tb=long --capture=sys --cov=laos --capture=fd laos/tests/${1:-functional} | grep TOTAL | awk '{print $4}'`
echo ${prev_stat_raw:0:2}
}
function get_coverage_delta {
local current_coverage=$(get_current_coverage)
local current_coverage=$(get_current_coverage $1)
local current_branch=`git branch | awk '{print $2}'`
echo -e "Falling back to ${1} commits."
local commits=`seq -f "^" -s '' ${1:-1}`
echo -e "Falling back to ${2} commits."
local commits=`seq -f "^" -s '' ${2}`
git checkout `git rev-parse --verify HEAD${commits}` &> /dev/null
local prev_coverage=$(get_current_coverage)
local prev_coverage=$(get_current_coverage $1)
echo -e "Current coverage: ${current_coverage}%"
echo -e "Previous coverage: ${prev_coverage}%"
if [ "${prev_coverage}" -gt "${current_coverage}" ]; then
@ -27,4 +27,4 @@ function get_coverage_delta {
}
get_coverage_delta ${1:-1}
get_coverage_delta ${1:-functional} ${2:-1}

15
tox.ini
View File

@ -1,7 +1,7 @@
# Project LaOS
[tox]
envlist = py35-functional,pep8
envlist = py35-functional,py35-functional-regression,py35-integration,py35-integration-regression,pep8
minversion = 1.6
skipsdist = True
@ -9,6 +9,13 @@ skipsdist = True
passenv =
PYTHONASYNCIODEBUG
TEST_DB_URI
FUNCTIONS_HOST
FUNCTIONS_PORT
FUNCTIONS_API_PROTO
FUNCTIONS_API_VERSION
OS_AUTH_URL
OS_PROJECT_ID
OS_TOKEN
setenv = VIRTUAL_ENV={envdir}
usedevelop = True
install_command = pip install -U {opts} {packages}
@ -26,13 +33,17 @@ commands = flake8
[testenv:venv]
commands = {posargs}
[testenv:py35-integration]
commands = pytest --tb=long --capture=sys --cov=laos --capture=fd {toxinidir}/laos/tests/integration
[testenv:py35-functional]
commands = pytest --tb=long --capture=sys --cov=laos --capture=fd {toxinidir}/laos/tests/functional
[testenv:py35-functional-regression]
commands = {toxinidir}/scripts/test_regression.sh {posargs}
commands = {toxinidir}/scripts/test_regression.sh functional {posargs}
[testenv:py35-integration-regression]
commands = {toxinidir}/scripts/test_regression.sh integration {posargs}
[testenv:docs]
commands =