avocado-framework/avocado

View on GitHub
selftests/unit/safeloader_core.py

Summary

Maintainability
D
1 day
Test Coverage
import os
import sys
import unittest
import unittest.mock
from collections import OrderedDict

from avocado.core.safeloader.core import find_avocado_tests, find_python_unittests
from avocado.utils import script
from selftests.utils import TestCaseTmpDir, setup_avocado_loggers

setup_avocado_loggers()


KEEP_METHODS_ORDER = """
from avocado import Test
from collections.abs import Sequence

class NotATest(Sequence[None]):
    pass

class MyClass(Test):
    def test2(self):
        pass

    def testA(self):
        pass

    def test1(self):
        pass

    def testZZZ(self):
        pass

    def test(self):
        pass
"""

IMPORT_NOT_NOT_PARENT_TEST = """
from avocado import Test
class SomeClass(Test):
    def test_something(self): pass

from logging import Logger, LogRecord
class Anyclass(LogRecord): pass
class Anyclass(Logger): pass
"""

RECURSIVE_DISCOVERY_TEST1 = """
# skip is not used, but stresses the safeloader
from avocado import skip, Test

class BaseClass(Test):
    def test_basic(self):
        pass

class FirstChild(BaseClass):
    def test_first_child(self):
        pass

class SecondChild(FirstChild):
    '''
    :avocado: disable
    '''
    def test_second_child(self):
        pass
"""

RECURSIVE_DISCOVERY_TEST2 = """
from avocado import Test
from recursive_discovery_test1 import SecondChild

class ThirdChild(Test, SecondChild):
    '''
    :avocado: recursive
    '''
    def test_third_child(self):
        pass
"""


RECURSIVE_DISCOVERY_PYTHON_UNITTEST = """
# main is not used, but stresses the safeloader
from unittest import main, TestCase

class BaseClass(TestCase):
    '''
    :avocado: tags=base-tag
    :avocado: tags=base.tag
    '''
    def test_maybe_replaced_by_child(self):
        pass

    def test_basic(self):
        pass

class Child(BaseClass):
    '''
    :avocado: tags=child-tag
    :avocado: tags=child.tag
    '''
    def test_maybe_replaced_by_child(self):
        pass

    def test_child(self):
        pass
"""

# The following definitions will be used while creating a directory
# structure that contains a pre-defined set of modules that will be
# used on tests below

# A level 0 library containing a base test class
L0_LIB = """
from avocado import Test
class BaseL0(Test):
    def test_l0(self):
        pass
"""

L1_LIB1 = """
from ..l0lib import BaseL0
class BaseL1(BaseL0):
    def test_l1(self):
        pass
"""

L1_LIB2 = """
from .. import l0lib
class BaseL1(l0lib.BaseL0):
    def test_l1(self):
        pass
"""

L2_LIB1 = """
from ...l0lib import BaseL0
class BaseL2(BaseL0):
    def test_l2(self):
        pass
"""

L2_LIB2 = """
from ... import l0lib
class BaseL2(l0lib.BaseL0):
    def test_l2(self):
        pass
"""

L2_LIB3 = """
from l0lib import BaseL0
class BaseL2(BaseL0):
    def test_l3(self):
        pass
"""


def get_this_file():
    this_file = __file__
    if this_file.endswith(".py"):
        return this_file
    elif this_file.endswith(".pyc") or this_file.endswith(".pyo"):
        return this_file[:-1]
    else:
        raise ValueError("Could not find the Python file associated with this module")


class UnlimitedDiff(unittest.TestCase):
    """
    Serves two purposes: as a base class to test safeloader.find_class_and_methods
    and, while at it, to set unlimited diff on failure results.
    """

    def setUp(self):
        self.maxDiff = None


class FindClassAndMethods(UnlimitedDiff):
    def test_self(self):
        reference = OrderedDict(
            {
                "UnlimitedDiff": [],
                "FindClassAndMethods": [
                    ("test_self", {}, []),
                    ("test_methods_order", {}, []),
                    ("test_import_not_on_parent", {}, []),
                    ("test_recursive_discovery", {}, []),
                    ("test_recursive_discovery_python_unittest", {}, []),
                ],
                "MultiLevel": [
                    ("test_base_level0", {}, []),
                    ("test_relative_level0_name_from_level1", {}, []),
                    ("test_relative_level0_from_level1", {}, []),
                    ("test_relative_level0_name_from_level2", {}, []),
                    ("test_relative_level0_from_level2", {}, []),
                    ("test_non_relative_level0_from_level2", {}, []),
                ],
            }
        )
        found = find_python_unittests(get_this_file())
        self.assertEqual(reference, found)

    def test_methods_order(self):
        avocado_keep_methods_order = script.TemporaryScript(
            "keepmethodsorder.py", KEEP_METHODS_ORDER
        )
        avocado_keep_methods_order.save()
        expected_order = ["test2", "testA", "test1", "testZZZ", "test"]
        tests = find_avocado_tests(avocado_keep_methods_order.path)[0]
        methods = [method[0] for method in tests["MyClass"]]
        self.assertEqual(expected_order, methods)
        avocado_keep_methods_order.remove()

    def test_import_not_on_parent(self):
        avocado_test = script.TemporaryScript(
            "import_not_not_parent_test.py", IMPORT_NOT_NOT_PARENT_TEST
        )
        avocado_test.save()
        expected = ["test_something"]
        tests = find_avocado_tests(avocado_test.path)[0]
        methods = [method[0] for method in tests["SomeClass"]]
        self.assertEqual(expected, methods)
        avocado_test.remove()

    def test_recursive_discovery(self):
        avocado_recursive_discovery_test1 = script.TemporaryScript(
            "recursive_discovery_test1.py", RECURSIVE_DISCOVERY_TEST1
        )
        avocado_recursive_discovery_test1.save()
        avocado_recursive_discovery_test2 = script.TemporaryScript(
            "recursive_discovery_test2.py", RECURSIVE_DISCOVERY_TEST2
        )
        avocado_recursive_discovery_test2.save()

        sys.path.append(os.path.dirname(avocado_recursive_discovery_test1.path))
        tests = find_avocado_tests(avocado_recursive_discovery_test2.path)[0]
        expected = {
            "ThirdChild": [
                ("test_third_child", {}, []),
                ("test_second_child", {}, []),
                ("test_first_child", {}, []),
                ("test_basic", {}, []),
            ]
        }
        self.assertEqual(expected, tests)

    def test_recursive_discovery_python_unittest(self):
        temp_test = script.TemporaryScript(
            "recursive_discovery_python_unittest.py",
            RECURSIVE_DISCOVERY_PYTHON_UNITTEST,
        )
        temp_test.save()
        tests = find_python_unittests(temp_test.path)
        expected = {
            "BaseClass": [
                (
                    "test_maybe_replaced_by_child",
                    {"base-tag": None, "base.tag": None},
                    [],
                ),
                ("test_basic", {"base-tag": None, "base.tag": None}, []),
            ],
            "Child": [
                (
                    "test_maybe_replaced_by_child",
                    {
                        "child-tag": None,
                        "child.tag": None,
                        "base-tag": None,
                        "base.tag": None,
                    },
                    [],
                ),
                (
                    "test_child",
                    {
                        "child-tag": None,
                        "child.tag": None,
                        "base-tag": None,
                        "base.tag": None,
                    },
                    [],
                ),
                (
                    "test_basic",
                    {
                        "base-tag": None,
                        "base.tag": None,
                        "child-tag": None,
                        "child.tag": None,
                    },
                    [],
                ),
            ],
        }
        self.assertEqual(expected, tests)


class MultiLevel(TestCaseTmpDir):
    def setUp(self):
        super().setUp()
        init = script.Script(
            os.path.join(self.tmpdir.name, "__init__.py"),
            "",
            mode=script.READ_ONLY_MODE,
        )
        init.save()
        l0 = script.Script(
            os.path.join(self.tmpdir.name, "l0lib.py"),
            L0_LIB,
            mode=script.READ_ONLY_MODE,
        )
        l0.save()

        l1_dir = os.path.join(self.tmpdir.name, "l1")
        os.mkdir(l1_dir)
        l11 = script.Script(
            os.path.join(l1_dir, "l1lib1.py"), L1_LIB1, mode=script.READ_ONLY_MODE
        )
        l11.save()
        l12 = script.Script(
            os.path.join(l1_dir, "l1lib2.py"), L1_LIB2, mode=script.READ_ONLY_MODE
        )
        l12.save()

        l2_dir = os.path.join(l1_dir, "l2")
        os.mkdir(l2_dir)
        l21 = script.Script(
            os.path.join(l2_dir, "l2lib1.py"), L2_LIB1, mode=script.READ_ONLY_MODE
        )
        l21.save()
        l22 = script.Script(
            os.path.join(l2_dir, "l2lib2.py"), L2_LIB2, mode=script.READ_ONLY_MODE
        )
        l22.save()
        l23 = script.Script(
            os.path.join(l2_dir, "l2lib3.py"), L2_LIB3, mode=script.READ_ONLY_MODE
        )
        l23.save()

    def test_base_level0(self):
        path = os.path.join(self.tmpdir.name, "l0lib.py")
        self.assertEqual(find_avocado_tests(path)[0], {"BaseL0": [("test_l0", {}, [])]})

    def test_relative_level0_name_from_level1(self):
        path = os.path.join(self.tmpdir.name, "l1", "l1lib1.py")
        self.assertEqual(
            find_avocado_tests(path)[0],
            {"BaseL1": [("test_l1", {}, []), ("test_l0", {}, [])]},
        )

    def test_relative_level0_from_level1(self):
        path = os.path.join(self.tmpdir.name, "l1", "l1lib2.py")
        self.assertEqual(
            find_avocado_tests(path)[0],
            {"BaseL1": [("test_l1", {}, []), ("test_l0", {}, [])]},
        )

    def test_relative_level0_name_from_level2(self):
        path = os.path.join(self.tmpdir.name, "l1", "l2", "l2lib1.py")
        self.assertEqual(
            find_avocado_tests(path)[0],
            {"BaseL2": [("test_l2", {}, []), ("test_l0", {}, [])]},
        )

    def test_relative_level0_from_level2(self):
        path = os.path.join(self.tmpdir.name, "l1", "l2", "l2lib2.py")
        self.assertEqual(
            find_avocado_tests(path)[0],
            {"BaseL2": [("test_l2", {}, []), ("test_l0", {}, [])]},
        )

    def test_non_relative_level0_from_level2(self):
        path = os.path.join(self.tmpdir.name, "l1", "l2", "l2lib3.py")
        sys_path = sys.path + [self.tmpdir.name]
        with unittest.mock.patch("sys.path", sys_path):
            self.assertEqual(
                find_avocado_tests(path)[0],
                {"BaseL2": [("test_l3", {}, []), ("test_l0", {}, [])]},
            )


if __name__ == "__main__":
    unittest.main()