summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'unittests')
-rw-r--r--unittests/base_tests.py2
-rw-r--r--unittests/framework/__init__.py0
-rw-r--r--unittests/framework/test_status.py139
-rw-r--r--unittests/status_tests.py300
4 files changed, 140 insertions, 301 deletions
diff --git a/unittests/base_tests.py b/unittests/base_tests.py
index 0f89139c2..28e40ade0 100644
--- a/unittests/base_tests.py
+++ b/unittests/base_tests.py
@@ -46,7 +46,7 @@ except ImportError:
pass
from . import utils
-from .status_tests import PROBLEMS, STATUSES
+from .framework.test_status import PROBLEMS, STATUSES
from framework.test.base import (
Test,
TestRunError,
diff --git a/unittests/framework/__init__.py b/unittests/framework/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/unittests/framework/__init__.py
diff --git a/unittests/framework/test_status.py b/unittests/framework/test_status.py
new file mode 100644
index 000000000..94f805a23
--- /dev/null
+++ b/unittests/framework/test_status.py
@@ -0,0 +1,139 @@
+# encoding=utf-8
+# Copyright © 2014, 2016 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+"""Tests for framework.status.
+
+This module does not have the comprehensive tests for all of the various
+combinations of comparisons between the various kinds of functions. Instead, it
+just asserts that the regressions, fixes, etc lists are as expected.
+
+"""
+
+from __future__ import (
+ absolute_import, division, print_function, unicode_literals
+)
+import itertools
+
+import pytest
+import six
+
+from framework import status
+
+
+# Statuses from worst to last. NotRun is intentionally not in this list and
+# tested separately because of upcoming features for it
+STATUSES = [
+ status.PASS,
+ status.WARN,
+ status.DMESG_WARN,
+ status.FAIL,
+ status.DMESG_FAIL,
+ status.TIMEOUT,
+ status.CRASH,
+ status.INCOMPLETE,
+]
+
+# all statuses except pass are problems
+PROBLEMS = STATUSES[1:]
+
+# Create lists of fixes and regressions programmatically based on the STATUSES
+# list. This means less code, and easier expansion changes.
+REGRESSIONS = list(itertools.combinations(STATUSES, 2)) + \
+ list(itertools.combinations([status.SKIP] + PROBLEMS, 2))
+FIXES = list(itertools.combinations(reversed(STATUSES), 2)) + \
+ list(itertools.combinations(list(reversed(PROBLEMS)) + [status.SKIP], 2))
+
+# The statuses that don't cause changes when transitioning from one another
+NO_OPS = [status.SKIP, status.NOTRUN]
+
+
+@pytest.mark.raises(exception=status.StatusException)
+def test_bad_lookup():
+ """status.status_lookup: An unexepcted value raises a StatusException"""
+ status.status_lookup('foobar')
+
+
+@pytest.mark.raises(exception=TypeError)
+def test_status_eq_raises():
+ """status.Status: eq comparison to uncomparable object results in TypeError"""
+ status.PASS == dict()
+
+
+@pytest.mark.raises(exception=TypeError)
+def test_nochangestatus_eq_raises():
+ """status.NoChangeStatus: eq comparison to uncomparable type results in TypeError"""
+ status.NOTRUN == dict()
+
+
+@pytest.mark.raises(exception=TypeError)
+def test_nochangestatus_ne_raises():
+ """status.NoChangeStatus: ne comparison to uncomparable type results in TypeError"""
+ status.NOTRUN != dict()
+
+
+def test_status_in():
+ """status.Status: A status can be looked up with 'x in y' synatx"""
+ stat = status.PASS
+ slist = ['pass']
+
+ assert stat in slist
+
+
+@pytest.mark.parametrize(
+ 'stat', itertools.chain(STATUSES, [status.SKIP, status.NOTRUN]))
+def test_lookup(stat):
+ status.status_lookup(stat)
+
+
+@pytest.mark.parametrize('new,old', REGRESSIONS)
+def test_regression(new, old):
+ assert status.status_lookup(new) < status.status_lookup(old)
+
+
+@pytest.mark.parametrize('new,old', FIXES)
+def test_fixes(new, old):
+ assert status.status_lookup(new) > status.status_lookup(old)
+
+
+@pytest.mark.parametrize('new,old', itertools.permutations(STATUSES, 2))
+def test_changes(new, old):
+ assert status.status_lookup(new) != status.status_lookup(old)
+
+
+@pytest.mark.parametrize('new,old', itertools.permutations(NO_OPS, 2))
+def test_no_change(new, old):
+ new = status.status_lookup(new)
+ old = status.status_lookup(old)
+ assert not new < old
+ assert not new > old
+
+
+@pytest.mark.parametrize("stat,op,expected", [
+ (status.Status('Test', 0, (0, 0)), six.text_type, 'Test'),
+ (status.Status('Test', 0, (0, 0)), six.binary_type, b'Test'),
+ (status.Status('Test', 0, (0, 0)), int, 0),
+ (status.Status('Test', 0, (0, 0)), repr, 'Status("Test", 0, (0, 0))'),
+ (status.Status('Test', 0, (0, 0)), hash, hash('Test')),
+ (status.NoChangeStatus('No'), hash, hash('No')),
+])
+def test_status_comparisons(stat, op, expected):
+ """Test status.Status equality protocol."""
+ assert op(stat) == expected
diff --git a/unittests/status_tests.py b/unittests/status_tests.py
deleted file mode 100644
index c2d62f8bf..000000000
--- a/unittests/status_tests.py
+++ /dev/null
@@ -1,300 +0,0 @@
-# Copyright (c) 2014 Intel Corperation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-""" Tests for the Status module
-
-Note: see framework/status.py for the authoritative list of fixes, regression,
-etc
-
-"""
-
-from __future__ import (
- absolute_import, division, print_function, unicode_literals
-)
-import itertools
-
-import nose.tools as nt
-import six
-
-import framework.status as status
-from . import utils
-
-# pylint: disable=expression-not-assigned,invalid-name,line-too-long
-
-# Statuses from worst to last. NotRun is intentionally not in this list and
-# tested separately because of upcoming features for it
-STATUSES = ["pass", "warn", "dmesg-warn", "fail", "dmesg-fail", "timeout",
- "crash", 'incomplete']
-
-# all statuses except pass are problems
-PROBLEMS = STATUSES[1:]
-
-# Create lists of fixes and regressions programmatically based on the STATUSES
-# list. This means less code, and easier expansion changes.
-REGRESSIONS = list(itertools.combinations(STATUSES, 2)) + \
- list(itertools.combinations(["skip"] + PROBLEMS, 2))
-FIXES = list(itertools.combinations(reversed(STATUSES), 2)) + \
- list(itertools.combinations(list(reversed(PROBLEMS)) + ["skip"], 2))
-
-# The statuses that don't cause changes when transitioning from one another
-NO_OPS = ('skip', 'notrun')
-
-
-@utils.nose.no_error
-def initialize_status():
- """status.Status: class inializes"""
- status.Status('test', 1)
-
-
-@utils.nose.no_error
-def initialize_nochangestatus():
- """status.NoChangeStatus: class initializes"""
- status.NoChangeStatus('test')
-
-
-@utils.nose.generator
-def test_gen_lookup():
- """ Generator that attempts to do a lookup on all statuses """
- @utils.nose.no_error
- def test(status_):
- status.status_lookup(status_)
-
- for stat in STATUSES + ['skip', 'notrun']:
- test.description = \
- "status.status_lookup: can lookup '{}' as expected".format(stat)
- yield test, stat
-
-
-@nt.raises(status.StatusException)
-def test_bad_lookup():
- """status.status_lookup: An unexepcted value raises a StatusException"""
- status.status_lookup('foobar')
-
-
-def test_status_in():
- """status.Status: A status can be looked up with 'x in y' synatx"""
- stat = status.PASS
- slist = ['pass']
-
- nt.ok_(stat in slist)
-
-
-@utils.nose.generator
-def test_is_regression():
- """ Generate all tests for regressions """
- def is_regression(new, old):
- """ Test that old -> new is a regression """
- nt.ok_(status.status_lookup(new) < status.status_lookup(old))
-
- for new, old in REGRESSIONS:
- is_regression.description = \
- "status.Status: '{}' -> '{}' is a regression as expected".format(
- old, new)
- yield is_regression, new, old
-
-
-@utils.nose.generator
-def test_is_fix():
- """ Generates all tests for fixes """
- def is_fix(new, old):
- """ Test that new -> old is a fix """
- nt.ok_(status.status_lookup(new) > status.status_lookup(old))
-
- for new, old in FIXES:
- is_fix.description = \
- "status.Status: '{}' -> '{}' is a fix as expected".format(
- new, old)
- yield is_fix, new, old
-
-
-@utils.nose.generator
-def test_is_change():
- """ Test that status -> !status is a change """
- def is_not_equivalent(new, old):
- """ Test that new != old """
- nt.ok_(status.status_lookup(new) != status.status_lookup(old))
-
- for new, old in itertools.permutations(STATUSES, 2):
- is_not_equivalent.description = \
- "status.Status: '{}' -> '{}' is a change as expected".format(
- new, old)
- yield is_not_equivalent, new, old
-
-
-@utils.nose.generator
-def test_not_change():
- """ Skip and NotRun should not count as changes """
- def check_not_change(new, old):
- """ Check that a status doesn't count as a change
-
- This checks that new < old and old < new do not return true. This is meant
- for checking skip and notrun, which we don't want to show up as regressions
- and fixes, but to go in their own special categories.
-
- """
- nt.assert_false(new < old,
- msg="{new} -> {old}, is a change "
- "but shouldn't be".format(**locals()))
- nt.assert_false(new > old,
- msg="{new} <- {old}, is a change "
- "but shouldn't be".format(**locals()))
-
- for nochange, stat in itertools.permutations(NO_OPS, 2):
- check_not_change.description = \
- "status.Status: {0} -> {1} is not a change".format(nochange, stat)
- yield (check_not_change, status.status_lookup(nochange),
- status.status_lookup(stat))
-
-
-@utils.nose.generator
-def test_max_statuses():
- """ Verify that max() works between skip and non-skip statuses """
- def _max_nochange_stat(nochange, stat):
- """ max(nochange, stat) should = stat """
- nt.assert_equal(
- stat, max(nochange, stat),
- msg="max({nochange}, {stat}) = {stat}".format(**locals()))
-
- def _max_stat_nochange(nochange, stat):
- """ max(stat, nochange) should = stat """
- nt.assert_equal(
- stat, max(stat, nochange),
- msg="max({stat}, {nochange}) = {stat}".format(**locals()))
-
- for nochange, stat in itertools.product(NO_OPS, STATUSES):
- nochange = status.status_lookup(nochange)
- stat = status.status_lookup(stat)
- _max_nochange_stat.description = \
- "status.Status: max({nochange}, {stat}) = {stat}".format(**locals())
- yield _max_nochange_stat, nochange, stat
-
- _max_stat_nochange.description = \
- "status.Status: max({stat}, {nochange}) = {stat}".format(**locals())
- yield _max_stat_nochange, nochange, stat
-
-
-def check_operator(obj, op, result):
- """ Test that the result of running an operator on an object is expected
-
- Arguments:
- obj -- an instance to test
- operator -- the operator to test on the object
- result -- the expected result
-
- """
- nt.assert_equal(op(obj), result)
-
-
-def check_operator_equal(obj, comp, op, result):
- """ Test that the result of running an operator on an object is expected
-
- Arguments:
- obj -- an instance to test
- operator -- the operator to test on the object
- result -- the expected result
-
- """
- nt.assert_equal(op(obj, comp), result)
-
-
-def check_operator_not_equal(obj, comp, op, result):
- """ Test that the result of running an operator on an object is expected
-
- Arguments:
- obj -- an instance to test
- operator -- the operator to test on the object
- result -- the expected result
-
- """
- nt.assert_not_equal(op(obj, comp), result)
-
-
-@utils.nose.generator
-def test_nochangestatus_magic():
- """ Test that operators unique to NoChangeStatus work """
- obj = status.NoChangeStatus('Test')
- stat = status.Status('Test', 0, (0, 0))
-
- # generator equality tests
- for comp, type_ in [(obj, 'status.NoChangeStatus'),
- (stat, 'status.Status'),
- ('Test', 'unicode')]:
- check_operator_equal.description = (
- 'Status.NoChangeStatus: Operator eq works with type: {}'.format(type_)
- )
- yield check_operator_equal, obj, comp, lambda x, y: x.__eq__(y), True
-
- check_operator_not_equal.description = (
- 'status.NoChangeStatus: Operator ne works with type: {}'.format(type_)
- )
- yield check_operator_not_equal, obj, comp, lambda x, y: x.__ne__(y), True
-
-
-@utils.nose.generator
-def test_status_magic():
- """ Generator for testing magic methods in the Status class """
- obj = status.Status('foo', 0, (0, 0))
- comparitor = status.Status('bar', 10, (0, 0))
-
- for func, name, result in [
- (six.text_type, 'unicode', 'foo'),
- (repr, 'repr', 'foo'),
- (int, 'int', 0)]:
- check_operator.description = \
- 'status.Status: Operator {} works'.format(name)
- yield check_operator, obj, func, result
-
- for func, name in [
- (lambda x, y: x.__lt__(y), 'lt'),
- (lambda x, y: y.__gt__(x), 'gt')]:
-
- check_operator_equal.description = \
- 'status.Status: Operator {0} works when True'.format(name)
- yield check_operator_equal, obj, comparitor, func, True
-
- for func, name in [
- (lambda x, y: x.__le__(x), 'le, when ='),
- (lambda x, y: x.__le__(y), 'le, when !='),
- (lambda x, y: x.__eq__(x), 'eq'),
- (lambda x, y: x.__ge__(x), 'ge, when ='),
- (lambda x, y: y.__ge__(x), 'ge, when !='),
- (lambda x, y: x.__ne__(y), 'ne'),
- (lambda x, y: x.__eq__(x), 'eq')]:
- check_operator_not_equal.description = \
- 'status.Status: Operator {0} works when False'.format(name)
- yield check_operator_not_equal, obj, comparitor, func, False
-
-
-@nt.raises(TypeError)
-def test_status_eq_raises():
- """status.Status: eq comparison to uncomparable object results in TypeError"""
- status.PASS == dict()
-
-
-@nt.raises(TypeError)
-def test_nochangestatus_eq_raises():
- """status.NoChangeStatus: eq comparison to uncomparable type results in TypeError"""
- status.NOTRUN == dict()
-
-
-@nt.raises(TypeError)
-def test_nochangestatus_ne_raises():
- """status.NoChangeStatus: ne comparison to uncomparable type results in TypeError"""
- status.NOTRUN != dict()