summaryrefslogtreecommitdiff
path: root/tests/mixins.py
blob: 5abaa75935855d5ec7e17aa14b1bca950ab64c7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt

"""
Test class mixins

Some of these are transitional while working toward pure-pytest style.
"""

import functools
import types
import unittest

import pytest

from coverage.misc import StopEverything


class EnvironmentAwareMixin:
    """
    Adapter from pytst monkeypatch fixture to our environment variable methods.
    """
    @pytest.fixture(autouse=True)
    def _monkeypatch(self, monkeypatch):
        """Get the monkeypatch fixture for our methods to use."""
        self._envpatcher = monkeypatch

    def set_environ(self, name, value):
        """Set an environment variable `name` to be `value`."""
        self._envpatcher.setenv(name, value)

    def del_environ(self, name):
        """Delete an environment variable, unless we set it."""
        self._envpatcher.delenv(name)


def convert_skip_exceptions(method):
    """A decorator for test methods to convert StopEverything to SkipTest."""
    @functools.wraps(method)
    def _wrapper(*args, **kwargs):
        try:
            result = method(*args, **kwargs)
        except StopEverything:
            raise unittest.SkipTest("StopEverything!")
        return result
    return _wrapper


class SkipConvertingMetaclass(type):
    """Decorate all test methods to convert StopEverything to SkipTest."""
    def __new__(cls, name, bases, attrs):
        for attr_name, attr_value in attrs.items():
            if attr_name.startswith('test_') and isinstance(attr_value, types.FunctionType):
                attrs[attr_name] = convert_skip_exceptions(attr_value)

        return super(SkipConvertingMetaclass, cls).__new__(cls, name, bases, attrs)


StopEverythingMixin = SkipConvertingMetaclass('StopEverythingMixin', (), {})


class StdStreamCapturingMixin:
    """
    Adapter from the pytest capsys fixture to more convenient methods.

    This doesn't also output to the real stdout, so we probably want to move
    to "real" capsys when we can use fixtures in test methods.

    Once you've used one of these methods, the capturing is reset, so another
    invocation will only return the delta.

    """
    @pytest.fixture(autouse=True)
    def _capcapsys(self, capsys):
        """Grab the fixture so our methods can use it."""
        self.capsys = capsys

    def stdouterr(self):
        """Returns (out, err), two strings for stdout and stderr."""
        return self.capsys.readouterr()

    def stdout(self):
        """Returns a string, the captured stdout."""
        return self.capsys.readouterr().out

    def stderr(self):
        """Returns a string, the captured stderr."""
        return self.capsys.readouterr().err