Move parallel runner plugin to core opencafe
Change-Id: I5008807d41584923d019db2cf7c75d46a3316b3d
This commit is contained in:
parent
47d0fb2023
commit
da5ce3f22a
|
@ -1,13 +0,0 @@
|
|||
# Copyright 2015 Rackspace
|
||||
# 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__('pkg_resources').declare_namespace(__name__)
|
|
@ -1,45 +0,0 @@
|
|||
# Copyright 2015 Rackspace
|
||||
# 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 setuptools import setup, find_packages
|
||||
from setuptools.command.test import test as TestCommand
|
||||
|
||||
|
||||
class Tox(TestCommand):
|
||||
"""
|
||||
Tox integration
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
TestCommand.__init__(self, *args, **kwargs)
|
||||
|
||||
def finalize_options(self):
|
||||
TestCommand.finalize_options(self)
|
||||
|
||||
def run_tests(self):
|
||||
# import here, cause outside the eggs aren't loaded
|
||||
import tox
|
||||
tox.cmdline(self.test_args)
|
||||
|
||||
setup(
|
||||
name='alt_unittest_runner',
|
||||
version='0.0.1',
|
||||
description='The Common Automation Framework Engine',
|
||||
author='Rackspace Cloud QE',
|
||||
author_email='cloud-cafe@lists.rackspace.com',
|
||||
url='http://rackspace.com',
|
||||
packages=find_packages(),
|
||||
namespace_packages=['cafe'],
|
||||
install_requires=[],
|
||||
tests_require=['tox'],
|
||||
cmdclass={'test': Tox},
|
||||
zip_safe=False)
|
|
@ -1,4 +0,0 @@
|
|||
tox
|
||||
mock
|
||||
flake8
|
||||
nose
|
|
@ -1,167 +0,0 @@
|
|||
# Copyright 2015 Rackspace
|
||||
# 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 unittest
|
||||
|
||||
from cafe.configurator.managers import EngineConfigManager
|
||||
from cafe.drivers.unittest.arguments import ArgumentParser
|
||||
from cafe.drivers.unittest.datasets import DatasetList
|
||||
from cafe.drivers.unittest.decorators import (
|
||||
data_driven_test, DataDrivenFixture)
|
||||
from cafe.engine.config import EngineConfig
|
||||
|
||||
|
||||
ENGINE_CONFIG = EngineConfig(
|
||||
os.environ.get("CAFE_ENGINE_CONFIG_FILE_PATH") or
|
||||
EngineConfigManager.ENGINE_CONFIG_PATH)
|
||||
|
||||
CONFIG_NAME = "test.config"
|
||||
TEST_CONFIG = "{0}{1}{2}".format(
|
||||
ENGINE_CONFIG.config_directory, os.sep, CONFIG_NAME)
|
||||
|
||||
|
||||
class PositiveDataGenerator(DatasetList):
|
||||
"""Generates positive tests for ArgumentParser"""
|
||||
def __init__(self):
|
||||
super(PositiveDataGenerator, self).__init__()
|
||||
self.append_new_dataset("Base", {"arg_update": [], "update": {}})
|
||||
self.append_new_dataset("tag_no_plus", {
|
||||
"arg_update": ["-t", "one", "two", "three"],
|
||||
"update": {"tags": ["one", "two", "three"]}})
|
||||
|
||||
self.append_new_dataset("tag_plus", {
|
||||
"arg_update": ["-t", "+", "two", "three"],
|
||||
"update": {"tags": ["two", "three"], "all_tags": True}})
|
||||
|
||||
self.append_new_dataset("data_directory", {
|
||||
"arg_update": ["-D", "/"],
|
||||
"update": {"data_directory": "/"}})
|
||||
|
||||
self.append_new_dataset("result_directory", {
|
||||
"arg_update": ["--result-directory", "/"],
|
||||
"update": {"result_directory": "/"}})
|
||||
|
||||
self.append_new_dataset("regex_list", {
|
||||
"arg_update": ["-d", ".*", "..."],
|
||||
"update": {"regex_list": [".*", "..."]}})
|
||||
|
||||
self.append_new_dataset("dry_run", {
|
||||
"arg_update": ["--dry-run"],
|
||||
"update": {"dry_run": True}})
|
||||
|
||||
self.append_new_dataset("exit_on_error", {
|
||||
"arg_update": ["--exit-on-error"],
|
||||
"update": {"exit_on_error": True}})
|
||||
|
||||
self.append_new_dataset("failfast", {
|
||||
"arg_update": ["--failfast"],
|
||||
"update": {"failfast": True}})
|
||||
|
||||
self.append_new_dataset("parallel_class", {
|
||||
"arg_update": ["--parallel", "class"],
|
||||
"update": {"parallel": "class"}})
|
||||
|
||||
self.append_new_dataset("parallel_test", {
|
||||
"arg_update": ["--parallel", "test"],
|
||||
"update": {"parallel": "test"}})
|
||||
|
||||
self.append_new_dataset("result_json", {
|
||||
"arg_update": ["--result", "json"],
|
||||
"update": {"result": "json"}})
|
||||
|
||||
self.append_new_dataset("result_xml", {
|
||||
"arg_update": ["--result", "xml"],
|
||||
"update": {"result": "xml"}})
|
||||
|
||||
for i in range(1, 4):
|
||||
i = str(i)
|
||||
self.append_new_dataset("verbose_" + i, {
|
||||
"arg_update": ["--verbose", i],
|
||||
"update": {"verbose": int(i)}})
|
||||
|
||||
for i in range(1, 4):
|
||||
i = str(i)
|
||||
self.append_new_dataset("workers_" + i, {
|
||||
"arg_update": ["--workers", i],
|
||||
"update": {"workers": int(i)}})
|
||||
|
||||
self.append_new_dataset("file", {
|
||||
"arg_update": ["--file", TEST_CONFIG],
|
||||
"update": {"file": {"tests.repo.cafe_tests.NoDataGenerator": [
|
||||
"test_fail", "test_pass"]}}})
|
||||
|
||||
self.append_new_dataset("list", {"arg_update": ["-l"]})
|
||||
|
||||
|
||||
@DataDrivenFixture
|
||||
class ArgumentsTests(unittest.TestCase):
|
||||
"""ArgumentParser Tests"""
|
||||
good_package = "tests.repo"
|
||||
bad_package = "tests.fakerepo"
|
||||
good_module = "tests.repo.cafe_tests"
|
||||
bad_module = "tests.repo.blah"
|
||||
bad_path = "tests."
|
||||
good_config = CONFIG_NAME
|
||||
base_arguments = [good_config, good_package]
|
||||
config = TEST_CONFIG
|
||||
expected_base = {
|
||||
"config": good_config,
|
||||
"testrepos": [good_package],
|
||||
"tags": [],
|
||||
"all_tags": False,
|
||||
"data_directory": None,
|
||||
"regex_list": [],
|
||||
"dry_run": False,
|
||||
"exit_on_error": False,
|
||||
"failfast": False,
|
||||
"parallel": None,
|
||||
"result": None,
|
||||
"result_directory": "./",
|
||||
"verbose": 2,
|
||||
"workers": 10,
|
||||
"file": {},
|
||||
"list": None}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(ArgumentsTests, cls).setUpClass()
|
||||
file_ = open(cls.config, "w")
|
||||
file_.write("test_fail (tests.repo.cafe_tests.NoDataGenerator)\n")
|
||||
file_.write("test_pass (tests.repo.cafe_tests.NoDataGenerator)\n")
|
||||
file_.close()
|
||||
|
||||
def get_updated_expected(self, **kwargs):
|
||||
"""Creates an updated base argument dictionary for compare"""
|
||||
dic = {}
|
||||
dic.update(self.expected_base)
|
||||
dic.update(kwargs)
|
||||
return dic
|
||||
|
||||
@data_driven_test(PositiveDataGenerator())
|
||||
def ddtest_arguments_positive(self, arg_update=None, update=None):
|
||||
"""Test different argument configurations"""
|
||||
arg_list = self.base_arguments + (arg_update or [])
|
||||
expected = self.get_updated_expected(**(update or {}))
|
||||
try:
|
||||
args = ArgumentParser().parse_args(arg_list)
|
||||
for key, value in expected.items():
|
||||
if key == "regex_list":
|
||||
self.assertEqual(
|
||||
value, [i.pattern for i in getattr(args, key, [])])
|
||||
else:
|
||||
self.assertEqual(value, getattr(args, key, "NoValueFound"))
|
||||
|
||||
except SystemExit as exception:
|
||||
if exception.code != 0:
|
||||
self.assertEqual(exception, None)
|
|
@ -1,136 +0,0 @@
|
|||
# Copyright 2015 Rackspace
|
||||
# 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 time import sleep
|
||||
from cafe.drivers.unittest.decorators import (
|
||||
tags, DataDrivenFixture, data_driven_test, DataDrivenClass)
|
||||
from cafe.drivers.unittest.datasets import DatasetList
|
||||
from cafe.drivers.unittest.fixtures import BaseTestFixture
|
||||
|
||||
DATASET = [1, 2]
|
||||
SLEEP_TIME = 0
|
||||
|
||||
|
||||
class TestDataGenerator(DatasetList):
|
||||
"""Data generator"""
|
||||
def __init__(self):
|
||||
super(TestDataGenerator, self).__init__()
|
||||
|
||||
for num in DATASET:
|
||||
self.append_new_dataset(
|
||||
name=str(num),
|
||||
data_dict={'num': num})
|
||||
|
||||
|
||||
class TestFixture(BaseTestFixture):
|
||||
"""Test Fixture for tests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestFixture, cls).setUpClass()
|
||||
sleep(SLEEP_TIME)
|
||||
cls.fixture_log.error(cls.__name__)
|
||||
|
||||
|
||||
class NoDataGenerator(TestFixture):
|
||||
"""Testing Non Data Generated class/test"""
|
||||
def test_pass(self):
|
||||
"""Testing pass case"""
|
||||
sleep(SLEEP_TIME)
|
||||
self.assertIn(1, DATASET)
|
||||
self.fixture_log.error("%s Pass", self.__class__.__name__)
|
||||
|
||||
def test_fail(self):
|
||||
"""Testing failure case"""
|
||||
sleep(SLEEP_TIME)
|
||||
self.fixture_log.error("%s Fail", self.__class__.__name__)
|
||||
self.assertIn(9, DATASET)
|
||||
|
||||
def test_error(self):
|
||||
"""Testing error case"""
|
||||
sleep(SLEEP_TIME)
|
||||
self.fixture_log.error("%s Error", self.__class__.__name__)
|
||||
raise Exception
|
||||
|
||||
|
||||
@DataDrivenFixture
|
||||
class DataGeneratedTests(TestFixture):
|
||||
"""Testing Data Driven Tests"""
|
||||
@tags("value", "value1", key='value')
|
||||
@data_driven_test(TestDataGenerator())
|
||||
def ddtest_pass(self, num):
|
||||
"""Testing pass case"""
|
||||
sleep(SLEEP_TIME)
|
||||
self.assertIn(num, DATASET)
|
||||
self.fixture_log.error("%s Pass", self.__class__.__name__)
|
||||
|
||||
@tags("value", "value1", key='value')
|
||||
@data_driven_test(TestDataGenerator())
|
||||
def ddtest_fail(self, num):
|
||||
"""Testing failure case"""
|
||||
sleep(SLEEP_TIME)
|
||||
self.fixture_log.error("%s Fail", self.__class__.__name__)
|
||||
self.assertNotIn(num, DATASET)
|
||||
|
||||
@tags("value", "value1", key='value')
|
||||
@data_driven_test(TestDataGenerator())
|
||||
def ddtest_error(self, num):
|
||||
"""Testing error case"""
|
||||
sleep(SLEEP_TIME)
|
||||
self.fixture_log.error("%s Error", self.__class__.__name__)
|
||||
raise Exception(num)
|
||||
|
||||
|
||||
@DataDrivenClass(TestDataGenerator())
|
||||
class DataGeneratedClasses(NoDataGenerator):
|
||||
"""Testing Data Driven Classes"""
|
||||
pass
|
||||
|
||||
|
||||
@DataDrivenClass(TestDataGenerator())
|
||||
class DataGeneratedClassesAndTests(DataGeneratedTests):
|
||||
"""Testing Data Driven Classes with Data Driven Tests"""
|
||||
pass
|
||||
|
||||
|
||||
class SetupFailNoDataGenerator(NoDataGenerator):
|
||||
"""Testing setUpClass failure for SetupFailNoDataGenerator"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(SetupFailNoDataGenerator, cls).setUpClass()
|
||||
raise Exception
|
||||
|
||||
|
||||
class SetupFailDataGeneratedTests(DataGeneratedTests):
|
||||
"""Testing setUpClass failure for SetupFailDataGeneratedTests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(SetupFailDataGeneratedTests, cls).setUpClass()
|
||||
raise Exception
|
||||
|
||||
|
||||
@DataDrivenClass(TestDataGenerator())
|
||||
class SetupFailDataGeneratedClasses(DataGeneratedClasses):
|
||||
"""Testing setUpClass failure for SetupFailDataGeneratedClasses"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(SetupFailDataGeneratedClasses, cls).setUpClass()
|
||||
raise Exception
|
||||
|
||||
|
||||
@DataDrivenClass(TestDataGenerator())
|
||||
class SetupFailDataGeneratedClassesAndTests(DataGeneratedClassesAndTests):
|
||||
"""Testing setUpClass failure for SetupFailDataGeneratedClassesAndTests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(SetupFailDataGeneratedClassesAndTests, cls).setUpClass()
|
||||
raise Exception
|
|
@ -1,17 +0,0 @@
|
|||
[tox]
|
||||
envlist=pep8,py27
|
||||
|
||||
[testenv]
|
||||
setenv=VIRTUAL_ENV={envdir}
|
||||
|
||||
deps=-r{toxinidir}/test-requirements.txt
|
||||
|
||||
[testenv:py27]
|
||||
commands=nosetests {toxinidir}
|
||||
|
||||
[testenv:pep8]
|
||||
commands=flake8
|
||||
|
||||
[flake8]
|
||||
ignore=F401
|
||||
exclude=.git,.idea,docs,.tox,bin,dist,tools,*.egg-info
|
|
@ -6,39 +6,43 @@ _cafe_runner()
|
|||
#get current word. sed for windows backslash
|
||||
cur=$(echo "${COMP_WORDS[COMP_CWORD]}"|sed 's/\\/\\\\/g')
|
||||
|
||||
#Consumer only exists in the parallel runner
|
||||
python -c "from cafe.drivers.unittest.runner import Consumer" 2>/dev/null
|
||||
#if status is == 0 then we are running parallel runner
|
||||
status=$?
|
||||
if [[ ${cur} == -* ]]; then
|
||||
options='--help --test-repo --verbose --fail-fast --supress-load-tests --packages --module-regex --module --method-regex --tags --result --result-directory --parallel --dry-run --data-directory --data --list'
|
||||
elif [[ ${COMP_CWORD} < 2 ]]; then
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_products;print_products()" 2>/dev/null)
|
||||
else
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_configs_by_product;print_configs_by_product(\"${COMP_WORDS[1]}\")" 2>/dev/null)
|
||||
fi
|
||||
|
||||
#parallel runner
|
||||
if [ $status -eq 0 ]; then
|
||||
if [[ ${cur} == -* ]]; then
|
||||
options='--help --dry-run --exit-on-error --list --data-directory --regex-list --file --parallel --result --result-directory --tags --verbose --workers'
|
||||
elif [[ ${COMP_CWORD} < 2 ]]; then
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_configs;print_configs()")
|
||||
else
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_imports;print_imports(\"${cur}\")")
|
||||
fi
|
||||
else #normal runner
|
||||
if [[ ${cur} == -* ]]; then
|
||||
options='--help --test-repo --verbose --fail-fast --supress-load-tests --packages --module-regex --module --method-regex --tags --result --result-directory --parallel --dry-run --data-directory --data --list'
|
||||
elif [[ ${COMP_CWORD} < 2 ]]; then
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_products;print_products()")
|
||||
else
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_configs_by_product;print_configs_by_product(\"${COMP_WORDS[1]}\")")
|
||||
fi
|
||||
options=$(echo $options|sed 's/\\/\\\\/g')
|
||||
COMPREPLY=( $(compgen -W '${options}' -- ${cur}) )
|
||||
return 0
|
||||
}
|
||||
|
||||
_cafe_parallel()
|
||||
{
|
||||
local cur options
|
||||
COMPREPLY=()
|
||||
|
||||
#get current word. sed for windows backslash
|
||||
cur=$(echo "${COMP_WORDS[COMP_CWORD]}"|sed 's/\\/\\\\/g')
|
||||
|
||||
if [[ ${cur} == -* ]]; then
|
||||
options='--help --dry-run --exit-on-error --list --data-directory --regex-list --file --parallel --result --result-directory --tags --verbose --workers'
|
||||
COMPREPLY="${COMPREPLY} "
|
||||
elif [[ ${COMP_CWORD} < 2 ]]; then
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_configs;print_configs()" 2>/dev/null)
|
||||
COMPREPLY="${COMPREPLY} "
|
||||
else
|
||||
options=$(python -c "from cafe.drivers.unittest.autocomplete import print_imports;print_imports(\"${cur}\")" 2>/dev/null)
|
||||
fi
|
||||
|
||||
#sed for windows backslash
|
||||
options=$(echo $options|sed 's/\\/\\\\/g')
|
||||
COMPREPLY=( $(compgen -W '${options}' -- ${cur}) )
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} < 2 ]]; then
|
||||
COMPREPLY="${COMPREPLY} "
|
||||
elif [ $status -ne 0 ]; then
|
||||
COMPREPLY="${COMPREPLY} "
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
complete -o nospace -F _cafe_runner cafe-runner
|
||||
|
||||
complete -F _cafe_runner cafe-runner
|
||||
complete -o nospace -F _cafe_parallel cafe-parallel
|
||||
|
||||
|
|
1
setup.py
1
setup.py
|
@ -109,6 +109,7 @@ setup(
|
|||
entry_points={
|
||||
'console_scripts':
|
||||
['cafe-runner = cafe.drivers.unittest.runner:entry_point',
|
||||
'cafe-parallel = cafe.drivers.unittest.runner_parallel:entry_point',
|
||||
'behave-runner = cafe.drivers.behave.runner:entry_point',
|
||||
'vows-runner = cafe.drivers.pyvows.runner:entry_point',
|
||||
'specter-runner = cafe.drivers.specter.runner:entry_point',
|
||||
|
|
Loading…
Reference in New Issue