Using pytest
Create a new file car.py and fill it with the following code. It defines the Car
class which has two methods: accelerate
and brake
:
class Car:
def __init__(self, speed=0):
self.speed = speed
def accelerate(self):
self.speed += 5
def brake(self):
self.speed -= 5
Now create test_car.py
with the following code:
import pytest
from car import Car
car = Car(30)
def test_accelerate():
car.accelerate()
assert car.speed == 35
def test_brake():
car.brake()
assert car.speed == 25
Here we've imported the Car
class from car.py and created an instance of Car
with the initial speed 30. The test_accelerate
and test_brake
methods will test the respective methods of the Car
class.
Note that pytest will only execute methods whose names begin with test
.
If JetBrains Fleet is in Smart Mode, and a Python interpreter has been configured for the project workspace, you should see run icons in the gutter next to test methods definitions. You can use them to run each test individually:

To run all tests at once, you can create a run configuration. Click the Run icon (Ctrl0R) and select Create Run Configurations in run.json.
A configuration for pytest must include "type": "python-tests"
and "testFramework": "pytest"
. Also, specify the name of the file with tests in target
:
{
"type": "python-tests",
"name": "test_my_car",
"testFramework": "pytest",
"targets": ["test_car"],
},
Run the configuration by pressingCtrl0R. A terminal with the tests results will open:

test_brake
has failed. Click it in the left pane to see the reason:

We assumed the car speed to be 25 after braking, but in fact it was 30. Why did that happen? The tests ran one after another, and the test_accelerate
method had changed the initial speed of the car. To avoid this effect, let's reinitialize the car inside each test:
import pytest
from car import Car
def test_accelerate():
car = Car(30)
car.accelerate()
assert car.speed == 35
def test_brake():
car = Car(30)
car.brake()
assert car.speed == 25
Now rerun the test_my_car configuration and make sure that all tests have passed:

Tests are designed to reveal problems in code. When you push the brake pedal in a real car it will either slow down or stop completely, depending on the initial speed. Let's check if the same is true for our Car
class.
The following test uses parametrization, add it to test_car.py:
@pytest.mark.parametrize("speeds", range(0,101))
def test_move(speeds):
car = Car(speeds)
car.brake()
distance = car.speed*1
assert distance >= 0
This test runs 100 times with the speeds in the range from 0 to 100. At each speed, the car is braked, and then we calculate how far it will go with the new speed in one hour. That distance must be equal to or greater than zero.
Run the tests:

If you click one of the failed test_move
tests, you'll see that it failed because the distance is negative.
Modify the brake
method of the Car
class to completely stop the car when its speed is 5 or less:
def brake(self):
if self.speed <= 5:
self.speed = 0
else:
self.speed -= 5
Now all tests pass:

Thanks for your feedback!