This page will give you some tutorial to create a test minimalist on your project.

Magic Tricks of Testing (summary) Sandy Metz

Incoming

Incoming Query (Assert Result)

class Whell:
    def __init__(self, rim, tire):
        self.rim = rim
        self.tire = tire

    def diameter(self):
        return self.rim + (self.tire * 2)


class TestWheel:
    def test_calculates_diameter(self):
        wheel = Whell(26, 1.5)

        assert wheel.diameter() == 29
        ## ⬆ Test the return value (result)

Incoming (private) Query

class Wheel:
    def __init__(self, rim, tire):
        self.rim = rim
        self.tire = tire

    def diameter(self):
        return self.rim + (self.tire * 2)

class Gear:
    def __init__(self, chainring, cog, wheel):
        self.chainring = chainring
        self.cog = cog
        self.wheel = wheel

    def _ratio(self):
        return self.chainring / self.cog

    def gear_inches(self):
        return self._ratio() * self.wheel.diameter()  # call private method


class TestGear:
    def test_calculates_gear_inches(self):
        wheel = Wheel(26, 1.5)
        gear = Gear(52, 11, wheel)

        assert gear.gear_inches() == pytest.approx(137, 0.01)
        ## ⬆ test the interface, not the implementation
        ## (without private function)

Incoming Command (Assert public side effect)

class Gear:
    def __init__(self):
        self.cog = 0

    def get_cog(self):
        return self.cog

    def set_cog(self, cog):
        self.cog = cog


class TestGear:
    def test_set_cog(self):
        gear = Gear()
        gear.set_cog(27)

        assert gear.cog == 27
        ## ⬆ assert public side effect

To Self

Sent to self (Ignore)

class Wheel:
    def __init__(self, rim, tire):
        self.rim = rim
        self.tire = tire

    def diameter(self):
        return self.rim + (self.tire * 2)


class Gear:
    def __init__(self, chainring, cog, wheel):
        self.chainring = chainring
        self.cog = cog
        self.wheel = wheel

    def _ratio(self):
        return self.chainring / self.cog

    def gear_inches(self):
        return self._ratio() * self.wheel.diameter()  # call private method


class TestGear:
    def test_calculates_ratio(self): ## ⬅ test private method
        wheel = Wheel(26, 1.5)
        gear = Gear(52, 11, wheel)

        assert gear._ratio == pytest.approx(4.7, 0.01) ## call to self
        ## ⬆ this is redundant test. `gear_inches` return value is proof enough
        ## don’t test private method (assert / expectation). Don’t!

Outgoing

Outgoing Query (Ignore)

class Wheel:
    def __init__(self, rim, tire):
        self.rim = rim
        self.tire = tire

    def diameter(self):
        return self.rim + (self.tire * 2)


class Gear:
    def __init__(self, chainring, cog, wheel):
        self.chainring = chainring
        self.cog = cog
        self.wheel = wheel

    def _ratio(self):
        return self.chainring / self.cog

    def gear_inches(self):
        return self._ratio() * self.wheel.diameter()  # call other class (outgoing)


class TestGear:
    def test_calculates_gear_inches(self):
        wheel = Wheel(26, 1.5)
        gear = Gear(52, 11, wheel)

        # test outgoing command `wheel.diameter()`
        assert gear.wheel.diameter() == 29
        ## ⬆ this is already done in `Wheel` test (redundant)

Outgoing Command (Expect to send)

# assert someting (side effect) in far away.
# This is not `Gear` responsibility.
# This is an integration test, not unit test.

Credits

https://www.youtube.com/watch?v=URSWYvyc42M

https://speakerdeck.com/skmetz/magic-tricks-of-testing-railsconf