object oriented – Best practices for seperating/designing classes and methods for use in testing

Since you’re creating a Docker container every time you run a test, and destroy it once the test is finished, the code which creates and destroys the container is, I imagine, in the SetUp/TearDown methods.

What you should consider is how different are those SetUp/TearDown methods from class to class.

  • If all they do is to call a method which would create/destroy the container, go with the base class option. This way, you’ll put SetUp/TearDown methods in the base class, and avoid a small duplication.

  • If some classes require additional setup, then you may consider the other approach.

In both cases, if creating/destroying a container takes more than one line, consider putting the code in a separate class. It doesn’t make sense to put all the creation/destruction logic in the test class, because it doesn’t belong there. Your test classes should look like this:

class SomeIntegrationTests:
    def setUp():
        testContext.container = docker.create()

    def tearDown():

    def testSomethingHere():

    def testOtherThings():

does it make sense to create classes in the main code that are specifically designed to be used within the tests, but also by the main code?

Absolutely. Your integration tests, when they test a specific part of your code, can rely on other parts which they don’t test.

You should be careful, however, that if the code that your tests rely on misbehaves, it may fail those tests as well, but it usually won’t be easy to identify the root cause.

Is there anything against creating classes/methods in the main code that are mainly used for tests?

Define mainly.

Production code should be limited to things that you need in production. If a piece of code is needed exclusively in tests, it doesn’t belong to production code: move it to the test project. If a piece of code is used in production, but also by the tests, you’re fine.