In large projects, at some point, a situation occurs when there are already a lot of tests on the project and in parallel, its own high-level framework is developing. The framework, in this case, as a wrapper over the functions of the testing object and the capabilities of various tools that are used in the project. In addition, all folders are filled with fixtures, many of which are used in only one test file.
At this wonderful moment, some problems arise. I already wrote about one of them, this is the implementation of convenient parameterization, for example, from a file . We'll talk about the next one of the most unfortunate in this article.
"Captain, we have a lot of fixtures and globals appear."
Overloading test directories with fixtures is quite a logical consequence of using the concept that is included in py.test, but sometimes this approach goes beyond the acceptable. In addition, we can often observe constructions in tests, which are designed to determine what information a test needs to take in a particular specific case, or a desire to initially check the possibility of further passing the test at the stage of preparing the environment.
The biggest misconception, in a situation where these constructs are passed from some setup
fixture and go along the entire test, is to use global
variables. I have faced similar difficult cases and this idea is one of the first to come to mind.
It's worth mentioning at this point that the concept of fixtures avoids this taint of code cleanliness, but also provides additional levels of abstraction and a lot of references. As a last resort, you can get a terrible habit of unpacking the result of a fixture, but in this case, we spoil the logs, because we do not have a division into Setup, Run and Teardown, and we additionally complicate the code at the time of unpacking the results or produce multiple shortcuts.
Let's look at some examples, and start with the worst:
"Fixtures and global"
import pytest
@pytest.fixture(autouse=True)
def setup(create_human, goto_room, goto_default_position, choose_window, get_current_view):
global human
global window
#
desired_room = 1 # ,
human = create_human("John", "Doe") #
# - ,
assert goto_room(human, desired_room), "{} {}".format(human.full_name, desired_room)
#
window = choose_window(desired_room)
view = get_current_view(window)
assert view, " {} ".format (window)
yield
# Teardown
goto_default_position(human)
@pytest.mark.parametrize(
"city, expected_result",
[
("New York", False),
("Berlin", False),
("Unknown", True)
]
)
def test_city_in_window(city, expected_result):
""" ."""
window_view = human.look_into(window)
recognized_city = human.recognize_city(window_view)
assert (recognized_city == city) == expected_result, " "
As a result:
- There are initial checks
- There is an ill-fated
global
" "
import pytest
@pytest.fixture
def setup(create_human, goto_room, goto_default_position, choose_window, get_current_view):
#
desired_room = 1 # ,
human = create_human("John", "Doe") #
# - ,
assert goto_room(human, desired_room), "{} {}".format(human.full_name, desired_room)
#
window = choose_window(desired_room)
view = get_current_view(window)
assert view, " {} ".format (window)
yield { "human": human, "window": window}
# Teardown
goto_default_position(human)
@pytest.mark.parametrize(
"city, expected_result",
[
("New York", False),
("Berlin", False),
("Unknown", True)
]
)
def test_city_in_window(setup, city, expected_result):
""" ."""
data = setup
window_view = data["human"].look_into(data["window"])
recognized_city = data["human"].recognize_city(window_view)
assert (recognized_city == city) == expected_result, " "
:
-
setup
- , ,
, 400+ , .
, 8 setup
: , ?
— . py.test, .
:
import pytest
class TestWindowView:
@pytest.fixture
def setup(self, create_human, goto_room, goto_default_position, choose_window, get_current_view):
#
desired_room = 1 # ,
self.human = create_human("John", "Doe") #
# - ,
assert goto_room(self.human, desired_room), "{} {}".format(human.full_name, desired_room)
#
self.window = choose_window(desired_room)
view = get_current_view(self.window)
assert view, " {} ".format (self.window)
yield
# Teardown
goto_default_position(self.human)
@pytest.mark.parametrize(
"city, expected_result",
[
("New York", False),
("Berlin", False),
("Unknown", True)
]
)
def test_city_in_window(self, setup, city, expected_result):
""" ."""
window_view = self.human.look_into(self.window)
recognized_city = self.human.recognize_city(window_view)
assert (recognized_city == city) == expected_result, " "
:
-
global
, .
, . , .
Android/iOS Appium IOT/Embedded .