Saturday, March 2, 2024

Three pytest Options You Will Love


Testing

One of the vital well-liked frameworks for Python is pytest, and it comes with a number of cool options. I’m going to point out you three of them on this weblog submit:

  • Fixtures
  • Markers
  • Parametrize

As you’d count on, PyCharm has full help for pytest, together with a devoted take a look at runner, code completion, and code navigation. To get began with pytest in PyCharm, it’s essential to set up and allow pytest as your take a look at runner.

Get began free of charge

Fixtures

It’s commonplace to arrange sources and situations for our assessments after which tear them down after our assessments have completed. Fixtures in pytest enable us to arrange these sources and situations in a constant, dependable, and repeatable approach. This could embody mocking/stubbing, database connections, file creation, dependency injection, and extra. 

By automating your take a look at preconditions on this approach, you may higher set up your code to make sure that your assessments give attention to enterprise logic, not the setup.

As a way to inform pytest that some code is a fixture, we have to add the @pytest.fixture decorator. On this instance, we’re utilizing a fixture to get a personality listing, which is required for the operate test_get_minimum_height.

@pytest.fixture
def fake_characters():
   return [
       {"name": "Luke", "height": 100},
       {"name": "Leia", "height": 50},
   ]

def test_get_minimum_height(fake_characters):
   outcome = swapi.get_minimum_height(fake_characters, 75)
   assert len(outcome) == 1

Fixtures in pytest allow you to maximise code reusability, be particular about your take a look at set-up and tear-down, and outline the scope you need them to use throughout your take a look at suite.

For instance, you should utilize the decorator @pytest.fixture(scope="module") on this context:

@pytest.fixture(scope=”module”)
def fake_characters():
   return [
       {"name": "Luke", "height": 100},
       {"name": "Leia", "height": 50},
   ]

def test_get_minimum_height(fake_characters):
   outcome = swapi.get_minimum_height(fake_characters, 75)
   assert len(outcome) == 1

Now the fake_characters fixture is about up at the beginning of the take a look at file or module and is cached for future use. All of our take a look at capabilities will share the identical occasion of the fixture.

Markers

Generally one dimension doesn’t match all. Maybe we have to run a subset of assessments when a sure situation is true or skip different assessments when a special situation is fake. We are able to do each of those with pytest. 

Let’s have a look at built-in pytest markers first. On this instance, we’ve added the decorator @pytest.mark.skip(purpose="skipping whereas I hunt bug-18463") to inform pytest to not run this take a look at. You shouldn’t routinely skip assessments, however typically it’s software to have. For instance, it’s extra useful than commenting out your take a look at and by accident checking that in to model management!

@pytest.mark.skip(purpose="skipping whereas I hunt bug-18463")
def get_shortest(self, threshold):
   return [character for character in self if int(character['height']) < threshold]

You may as well skip assessments based mostly on sure situations through the use of the -skipif argument. 

For instance, you may enhance a take a look at with @pytest.mark.skipif() to say {that a} take a look at does (or doesn’t) run on a particular working system:

@pytest.mark.skipif(platform.system() == 'Darwin', purpose="Take a look at does not run on macOS")
def test_get_characters(fake_characters):
   assert fake_characters[0]["name"] == "Luke"

The above code would inform pytest to skip this take a look at if the working system is macOS, however run it for different working methods. As a facet be aware, the macOS identifier right here is ‘Darwin’ due to its Linux heritage. You’ll be able to test the identifier through the use of the platform.system() technique. 

One other use for @pytest.mark.skipif is to outline a minimal Python model for the take a look at:

@pytest.mark.skipif(sys.version_info < (3, 9), purpose="Take a look at solely runs on Python 3.9 and better")
def test_get_characters(fake_characters):
   assert fake_characters[0]["name"] == "Luke"

This code says that the take a look at solely runs on Python 3.9 or greater. You’ll be able to view a listing of the built-in markers in pytest by operating the next command in your terminal:

$ pytest --markers

You may as well add your personal customized metadata to markers. For instance, we will add the pytest.mark.comparability() decorator to this take a look at:

@pytest.mark.peak(purpose="It is a peak take a look at")
def get_shortest(self, threshold):
   return [character for character in self if int(character['height']) < threshold]

After we run this take a look at, pytest will solely run assessments adorned with this marker by specifying the marker (peak):

$ pytest -m peak

Whereas pytest will run your take a look at for you, it would additionally warn you that customized marks ought to be registered in your configuration file. The pytest documentation for customized markers has directions on how to do that. 

Parametrize

@parametrize is one other marker decorator in pytest that permits you to inform pytest to run the identical take a look at with totally different enter parameters. Which means if in case you have a operate that accepts totally different inputs and anticipated outputs, you may write one take a look at and use the @parametrize decorator, which vastly simplifies your code and improves the readability.

For instance, on this code, we’ve used @pytest.mark.parametrize() to go three plenty of arguments into the test_get_minimum_heights() take a look at. 

def test_get_minimum_height(fake_characters):
   outcome = swapi.get_minimum_height(fake_characters, 75)
   assert len(outcome) == 1
@pytest.mark.parametrize('threshold, depend', [
   [120, 0],
   [75, 1],
   [200, 2],
])
def test_get_minimum_heights(fake_characters, threshold, depend):
   outcome = swapi.get_minimum_height(fake_characters, threshold)
   assert len(outcome) == depend

After we run this take a look at, pytest runs it thrice, treating every run as a separate take a look at:

The @parametrize decorator is useful while you need one take a look at to obtain a number of inputs and anticipated outcomes.

Sources and additional studying

If you wish to study extra about fixtures, markers, and parametrize in pytest, listed here are some sources that you could take a look at:

image description

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles