使用unittest时如何自由组合多个setUp()/tearDown() base 类?
How to freely combine multiple setUp()/tearDown() base classes while using unittest?
有多种设置:创建应用程序驱动程序、创建虚拟设备、进行登录。
一些测试用例只需要应用程序驱动程序,一些需要应用程序驱动程序和登录,一些需要应用程序驱动程序和设备,其他三者都需要。
如何制作类似 Combine<Ts...>
模板的东西:
#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;
}
输出:
Login setup
Device setup
test
Login teardown
Device teardown
Device setup
Device teardown
使用 mixin、多重继承和 super()
调用:
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()
有多种设置:创建应用程序驱动程序、创建虚拟设备、进行登录。
一些测试用例只需要应用程序驱动程序,一些需要应用程序驱动程序和登录,一些需要应用程序驱动程序和设备,其他三者都需要。
如何制作类似 Combine<Ts...>
模板的东西:
#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;
}
输出:
Login setup
Device setup
test
Login teardown
Device teardown
Device setup
Device teardown
使用 mixin、多重继承和 super()
调用:
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()