Thursday, February 29, 2024
HomePythonThree pytest Options You Will Love

Three pytest Options You Will Love


Testing

One of the common frameworks for Python is pytest, and it comes with a number of cool options. I’m going to indicate you three of them on this weblog put up:

  • Fixtures
  • Markers
  • Parametrize

As you’d anticipate, PyCharm has full assist 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 worthwhile to set up and allow pytest as your take a look at runner.

Get began at no cost

Fixtures

It’s commonplace to arrange assets and circumstances for our exams after which tear them down after our exams have completed. Fixtures in pytest permit us to arrange these assets and circumstances in a constant, dependable, and repeatable approach. This will embrace mocking/stubbing, database connections, file creation, dependency injection, and extra. 

By automating your take a look at preconditions on this approach, you may higher manage your code to make sure that your exams concentrate on enterprise logic, not the setup.

So as 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 record, 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):
   consequence = swapi.get_minimum_height(fake_characters, 75)
   assert len(consequence) == 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):
   consequence = swapi.get_minimum_height(fake_characters, 75)
   assert len(consequence) == 1

Now the fake_characters fixture is about up at first 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 exams when a sure situation is true or skip different exams when a distinct situation is fake. We will do each of those with pytest. 

Let’s take 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 exams, 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 can even skip exams based mostly on sure circumstances by utilizing the -skipif argument. 

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

@pytest.mark.skipif(platform.system() == 'Darwin', purpose="Check 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 programs. As a aspect observe, the macOS identifier right here is ‘Darwin’ due to its Linux heritage. You possibly can verify the identifier by utilizing 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="Check 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 increased. You possibly can view a listing of the built-in markers in pytest by operating the next command in your terminal:

$ pytest --markers

You can even add your individual customized metadata to markers. For instance, we will add the pytest.mark.comparability() decorator to this take a look at:

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

Once we run this take a look at, pytest will solely run exams embellished with this marker by specifying the marker (top):

$ pytest -m top

Whereas pytest will run your take a look at for you, it can additionally warn you that customized marks needs 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 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 now have used @pytest.mark.parametrize() to go three a lot of arguments into the test_get_minimum_heights() take a look at. 

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

Once we run this take a look at, pytest runs it 3 times, 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 be taught extra about fixtures, markers, and parametrize in pytest, listed below are some assets you can try:

image description

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments