I wasn't interested in replacing every assert statement, so instead I created a compatibility module. For every testify assertion I used, I wrote a function with the same name and a very simple implementation using the assert statement.
This module is at testing/testifycompat.py
Then I replaced all testify
imports with from testing.testifycompact import ...
I only used a few fixtures, so I was able to replace most of them with the following regex:
s/@setup$/@pytest.fixture(autouse=True)/
s/@setup_teardown/@pytest.yield_fixture(autouse=True)/
@teardown is a little more difficult (at least I didn't find a simple replacement for it). Instead I replaced these with @pytest.yield_fixture(autouse=True) and put a yield statement on the first line. This could probably be handled better by creating a testing.testifycompact.teardown() which uses a finalizer .
This is where it got a little more difficult. My class names used a suffix convention (SomethingSomethingTestCase), but py.test only supports class prefix . I used a regex to move most of these to a Test profix (and remove the TestCase base class)
/class (.*)TestCase\(TestCase\)/class Test1(object)/
This mostly worked, but I did end up with some errors where other classes which started with Test were causing discovery failures, and where my naming convention wasn't followed. I had to compare test count with testify against the new count to find the tests that were missed.
I would like to look into supporting discovery based on the TestCase baseclass by creating a testify.tesetifycompat.TestCase that served only as a sentinel for discovery.