1

There are various setups: creating an app driver, creating a dummy device, doing a login.

Some test cases need only app-driver, some need app-driver and login, some need app-driver and device, others use all three.

How to make something like a Combine<Ts...> template:

#include <iostream>

// The unittest.TestCase.
struct TestCase
{
    virtual void setUp() {}
    virtual void tearDown() {}
};

template <typename ...Ts>
struct Combine: public TestCase, public Ts...
{
    virtual void setUp() override { int t[] = { 0, (Ts::setUp(), 1)... }; }

    // TODO: invert the order
    virtual void tearDown() override { int t[] = { 0, (Ts::tearDown(), 1)... }; }
};

// Setups for 'login' only.
struct Login
{
    void setUp() { std::cout << "Login setup" << std::endl; }
    void tearDown() { std::cout << "Login teardown" << std::endl; }
};

// Setups for 'device' only.
struct Device
{
    void setUp() { std::cout << "Device setup" << std::endl; }
    void tearDown() { std::cout << "Device teardown" << std::endl; }
};

// A concrete test case.
struct MyTest: public Combine<Login, Device>
{
    void test() { std::cout << "test" << std::endl; }
};

int main()
{
    MyTest cd;
    cd.setUp();
    cd.test();
    cd.tearDown();
    Combine<Device> d;
    d.setUp();
    d.tearDown();
    return 0;
}

Output:

Login setup
Device setup
test
Login teardown
Device teardown
Device setup
Device teardown

1 Answer 1

2

Use mixins, multiple inheritance and super() calls:

import unittest

class MixinBase(object):
    def setUp(self):
        pass

    def tearDown(self):
        pass


class LoginMixin(MixinBase):
    def setUp(self):
        print("LoginMixin.setUp()")
        self.login = "login"
        super(LoginMixin, self).setUp()

    def tearDown(self):
        super(LoginMixin, self).tearDown()
        print("LoginMixin.tearDown()")
        del self.login


class DeviceMixin(MixinBase):
    def setUp(self):
        print("DeviceMixin.setUp()")
        self.device = "device"
        super(DeviceMixin, self).setUp()

    def tearDown(self):
        super(DeviceMixin, self).tearDown()
        print("DeviceMixin.tearDown()")
        del self.device



class TestThatOnlyNeedsLogin(LoginMixin, unittest.TestCase):
    def test_something(self):
        self.assertEqual(self.login, "login")


class TestThatNeedsLoginAndDevice(LoginMixin, DeviceMixin, unittest.TestCase):
    def test_something(self):
        self.assertEqual(self.login, "login")
        self.assertEqual(self.device, "device")

# XXX actually useless (multiple inheritance works fine)
# but since you asked for it
def combinemixins(cls, *otherbases):
    bases = (cls,)  + otherbases
    Combined = type.__new__(type, "Combined", bases, {})
    return Combined

LoginAndDevice = combinemixins(LoginMixin, DeviceMixin)

class TestWithCombined(LoginAndDevice, unittest.TestCase):
    def test_something(self):
        self.assertEqual(self.login, "login")
        self.assertEqual(self.device, "device")


if __name__ == "__main__":
    unittest.main()
Sign up to request clarification or add additional context in comments.

1 Comment

@velkan so does it answer your question ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.