Suppose that I have an interface defined like this:
class MyInterface(abc.ABCMeta):
#abstractmethod
def my_method(self, *params):
pass
And several implementations of it.
class Implentation1(MyInterface):
pass
class Implentation2(MyInterface):
pass
All of these classes must be tested under the same class. I was wondering it there is any way to specify that you want a test case to be run with different classes. I am using nosetests and unittest.
Related
I am implementing multiple RL agents which share a lot of common attributes and methods but differ in only one. Namely the one that calculates the td_error. Out of the top of my head I can think of 3 options to implement this:
Use an Agent abstract class (ABCMeta) and let the subclasses each implement all their methods.
Use a normal base class Agent, implement all the common methods and just do pass on the one that is specific to each subclass.
Use just one class Agent and use an attribute to specify the type of td_error to calculate and then just use if else to achieve the specific behavior.
Here is what I don't like about each option:
It seems I would need to repeat myself when implementing the common methods in each subclass.
It would be possible to create instances of the base class Agent but it wouldn't work since the specific function is not defined.
It is ugly and seems very naive.
I have been presented with this situation before and I normally go with option 2. but I am pretty sure there is a more correct way of achieving this.
You most definitely do not have to repeat yourself with Abstract class. If you define methods without decorating them as abstract, they will work just fine and can be used in child classes.
from abc import ABC, abstractmethod
class Polygon(ABC):
def amPolygon(self):
print("I am polygon")
#abstractmethod
def noofsides(self):
raise NotImplementedError
class Triangle(Polygon):
# overriding abstract method
def noofsides(self):
print("I have 3 sides")
class Pentagon(Polygon):
# overriding abstract method
def noofsides(self):
print("I have 5 sides")
R = Pentagon()
R.amPolygon()
I have a code that runs a simulation. To setup the simulation I have multiple classes:
They need to be used one after the other since information is inherited from one to the other. However, I was wondering how to best organize everything?
I would like to have one big parent class called "sim", then to access the functions in each class, I would like to be able to write:
sim.geometry.rectangle(...)
or
sim.run.parameter_scan(...)
Kind of like python packages, where one writes: os.path.join(...)
In order to do this, do I need to write something like:
class sim():
def __init__(self):
pass
class general():
...
class geometry():
...
class run():
...
etc.
I've written some tests using unittest as below and I want to reuse them in another class where I'm stuck and need help..
Code snippets are as below.
MyTestClass.py
Class MyTestClass(unittest.TestCase):
#classmethod
def test_TC01_set(self):
self.devAddr = "127.0.0.0"
self.teststoSkip = 'TC02'
def skip(type):
if type in self.teststoSkip:
self.skipTest('skipped!!') #unittest.Testcase method
def test_TC02(self):
self.skip('TC02')
print 'test_TC02 will do other tasks'
def test_TC03(self):
self.skip('TC03')
print 'test_TC03 will do other tasks'
This will work fine. Now I want to reuse the same testcases in another class. say,
RegressionMyTest.py
from MyTestClass import MyTestClass
Class RegressionMyTest(MyTestClass):
#classmethod
def setupmytest(self):
self.test_TC01_set(self)#this will work fine since it is accessing classmethod
self.tes_TC02(self)#cant access like this since it is not a class method
self.tes_TC03(self)#cant access like this since it is not a class method
How can I reuse the tests in MyTestClass in RegressionMyTest so that both MyTestClass and RegressionMyTest should work if they are run individually using nosetests/unittest.
Usually tests are supposed to assert code is functioning in a certain way, so I'm not sure if it would make sense to actually share tests between testsuites, (I don't think it would be very explicit)
Python tests cases are just python classes, that are introspected by the test runner for methods beginning in test_. Because of this you can you use inheritance in the same way you would with normal classes.
If you need shared functionality, you could create a base class with shared initialization methods/ helper methods. Or create testing mixins with utility functions that are needed across tests.
class BaseTestCase(unittest.TestCase):
def setUp(self):
# ran by all subclasses
def helper(self):
# help
class TestCaseOne(BaseTestCase):
def setUp(self):
# additional setup
super(TestCaseOne, self).setUp()
def test_something(self):
self.helper() # <- from base
Perhaps you don't want to define a setup method on the base class and just define on child classes using some helper methods defined in the base class? Lots of options!
I don't think your title describe your question correctly. Your code mistake is:
Calling a parent class "object method" in the child "class method"(#classmethod), because an "object method" must have one class instance(object), so in the child "class method", the system could find any object instance for its parent class.
You just need review the concepts of "class methods" and "object methods"(or instance methods) in programming language.
I'm trying to pick up Python for a project, and I'm a bit confused about how to use abstraction and classes. (I'm not a very experienced programmer, so apologies for the basic level of this question.) I come from a Java/Ocaml background, and what I've been trying to do is as follows: I have abstract classes for a graph and a graphadvanced (a graph with some more fancy methods), that look something like this
class AbstractGraph:
def method1(self):
raise NotImplementedError
...
class AbstractAdvanced:
def method2(self):
raise NotImplementedError
...
I then have an implementation of a graph:
class Graph(AbstractGraph):
def method1(self):
* actual code *
Now my question is: can I do something like this?
class Advanced(AbstractAdvanced, AbstractGraph):
def method2(self):
*actual code, using the methods from AbstractGraph*
In other words, how can I define the methods of Advanced abstractly in terms of the methods of AbstractGraph, and then somehow pass Graph into a constructor to get an instance of Advanced that uses Advanced's definitions with Graph's implementation?
In terms of Ocaml, I'm trying to treat AbstractAdvanced and AbstractGraph as module types, but I've played around a little with python and I'm not sure how to get this to work.
If you want to create abstract base classes, you can, but they are of limited utility. It's more normal to start your class hierarchy (after inheriting from object, or some other third-party class) with concrete classes.
If you want to create a class that pieces together various classes that partially some protocol, then just inherit from your implementing classes:
#Always inherit from object, or some subtype thereof, unless you want your code to behave differently in python 2 and python 3
class AbstractGraph(object):
def method1(self):
raise NotImplementedError
class Graph(AbstractGraph):
def method1(self):
* actual code *
class GraphToo(AbstractGraph):
def method1(self):
* actual code *
class AbstractAdvanced(AbstractGraph):
def method2(self):
raise NotImplementedError
class Advanced(Graph,AbstractAdvanced):
def method2(self):
*actual code, using the methods from Graph*
# order of classes in the inheritance list matters - it will affect the method resolution order
class AdvancedToo(GraphToo, Advanced): pass
I have several classes that share some invariants and have a common interface, and I would like to run automatically the same test for each of them.
As an example, suppose I have several classes that implement different approaches for partitioning a data-set. The common invariant here would be, that for all of these classes the union over all partitions should equal the original data-set.
What I currently have looks something like this:
class PartitionerInvariantsTests(unittest.TestCase):
def setUp(self):
self.testDataSet = range(100) # create test-data-set
def impl(self, partitioner):
self.assertEqual(self.testDataSet,
chain.from_iterable(partitioner(self.testDataSet))
Then I add a different function that calls impl for each of the classes I want to test with an instance of that class. The problem with this becomes apparent when doing this for more than one test-function. Suppose I have 5 test-functions and 5 classes I want to test. This would make 25 functions that look almost identical for invoking all the tests.
Another approach I was thinking about was to implement the template as a super-class, and then create a sub-class for each of the classes I want to test. The sub-classes could provide a function for instantiating the class. The problem with that is that the default test-loader would consider the (unusable) base-class a valid test-case and try to run it, which would fail.
So, what are your suggestions?
P.S.: I am using Python 2.6
You could use multiple inheritance.
class PartitionerInvariantsFixture(object):
def setUp(self):
self.testDataSet = range(100) # create test-data-set
super(PartitionInvariantsFixture, self).setUp()
def test_partitioner(self):
TestCase.assertEqual(self.testDataSet,
chain.from_iterable(self.partitioner(self.testDataSet))
class MyClassTests(TestCase, PartitionerInvariantsFixture):
partitioner = Partitioner
Subclass PartitionerInvariantsTests:
class PartitionerInvariantsTests(unittest.TestCase):
def test_impl(self):
self.assertEqual(self.testDataSet,
chain.from_iterable(self.partitioner(self.testDataSet))
class PartitionerATests(PartitionerInvariantsTests):
for each Partitioner class you wish to test. Then test_impl would be run for each Partitioner class, by virtue of inheritance.
Following up on Nathon's comment, you can prevent the base class from being tested by having it inherit only from object:
import unittest
class Test(object):
def test_impl(self):
print('Hi')
class TestA(Test,unittest.TestCase):
pass
class TestB(Test,unittest.TestCase):
pass
if __name__ == '__main__':
unittest.sys.argv.insert(1,'--verbose')
unittest.main(argv = unittest.sys.argv)
Running test.py yields
test_impl (__main__.TestA) ... Hi
ok
test_impl (__main__.TestB) ... Hi
ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK