Inheriting setUp method Python Unittest - python

I have a question regarding unittest with Python! Let's say that I have a docker container set up that handles a specific api endpoint (let's say users, ex: my_site/users/etc/etc/etc). There are quite a few different layers that are broken up and handled for this container. Classes that handle the actual call and response, logic layer, data layer. I am wanting to write tests around the specific calls (just checking for status codes).
There are a lot of different classes that act as Handlers for the given endpoints. There are a few things that I would have to set up differently per one, however, each one inherits from Application and uses some methods from it. I am wanting to do a setUp class for my unittest so I don't have to re-establish this each time. Any advice will help. So far I've mainly seen that inheritance is a bad idea with testing, however, I am only wanting to use this for setUp. Here's an example:
class SetUpClass(unittest.TestCase):
def setUp(self):
self._some_data = data_set.FirstOne()
self._another_data_set = data_set.SecondOne()
def get_app(self):
config = Config()
return Application(config,
first_one=self._some_data,
second_one=self._another_data_set)
class TestFirstHandler(SetUpClass, unittest.TestCase):
def setUp(self):
new_var = something
def tearDown(self):
pass
def test_this_handler(self):
# This specific handler needs the application to function
# but I don't want to define it in this test class
res = self.fetch('some_url/users')
self.assertEqual(res.code, 200)
class TestSecondHandler(SetUpClass, unittest.TestCase):
def setUp(self):
different_var_thats_specific_to_this_handler = something_else
def tearDown(self):
pass
def test_this_handler(self):
# This specific handler needs the application to function
# but I don't want to define it in this test class
res = self.fetch('some_url/users/account/?something_custom={}'.format('WOW'))
self.assertEqual(res.code, 200)
Thanks again!!

As mentioned in the comments, you just need to learn how to use super(). You also don't need to repeat TestCase in the list of base classes.
Here's the simple version for Python 3:
class TestFirstHandler(SetUpClass):
def setUp(self):
super().setUp()
new_var = something
def tearDown(self): # Easier to not declare this if it's empty.
super().tearDown()
def test_this_handler(self):
# This specific handler needs the application to function
# but I don't want to define it in this test class
res = self.fetch('some_url/users')
self.assertEqual(res.code, 200)

Related

Django. How to create model instance in test db using objects fabric?

I want to make my unit tests setUp function clear from repeating tons of model creation lines like 1) create user 2) now create employee with fk to this user and etc.
In order to do that I've made a simple factory of dummy objects but I might've done some mistakes or just misunderstood something. Here's a piece of factory (dummy_data is just a bunch of dicts):
from abc import ABC
from users.models import User
from employees.models import Employee
from .dummy_data import(
user_data,
employee_data,
)
class DummyObjectFactory(ABC):
"""Fabric representing dummy test objects"""
def get_dummy_object(self):
"""Return dummy object"""
class DummyUser(DummyObjectFactory):
def get_dummy_object(self) -> User:
return User.objects.create_user(**user_data)
class DummyEmployee(DummyObjectFactory):
def get_dummy_object(self) -> Employee:
user = DummyUser().get_dummy_object()
return Employee.objects.create(**employee_data, user=user)
dummy_factory = {
"User": DummyUser().get_dummy_object(),
"Employee": DummyEmployee().get_dummy_object(),
}
dummy_factory = dot_dict(dummy_factory)
Then I make a dot notaion dictionary of all kinds of fabrics for easy calling them buy dummy_factory.Name . My intetion was that I call fabric with the desired model name and it creates it's instance.
The problem is: when I call it in some test's setUp method like so test_user = dummy_factory.User it creates object in actual database but I want it to be in test database.
Example of test:
class TestEmployeesListView(TestCase):
def setUp(self):
self.test_user = dummy_factory.User
self.test_employee = dummy_factory.Employee
self.client = Client()
def test_listview_deny_anonymous_user(self):
response = self.client.get(reverse('employees:employees-list'))
self.assertRedirects(response, '/login/?next=/employees/')
Yes, I've searched for the solution and found Factory boy and Faker libraries, but I want to complete my fabric, make it work properly. Thanks for your attention.
So I made it work. What I did was:
Added #abstractmethod decorator in the abstract class.
Every concrete factory methods must have a #classmethod decorator and recieve cls as an argument:
class DummyUser(DummyObjectFactory):
#classmethod
def get_dummy_object(cls) -> User:
return User.objects.create_user(**user_data)
It just work as intended: factory creates objects in test db. Thank you folks for participation.

Refactor the python design patterns

I have a class called resources and I have defined one method called get_connect. I want to use the data of which get_connect returns to the other classes. I need at least three classes and I use the data of get_connect and I have to parse that data. To implement this I have written the code below
class resources:
#staticmethod
def get_connect():
return 1 + 2
class Source1(resources):
def __init__(self):
self.response = resources.get_connect()
def get__details1(self):
print(self.response)
class Source2(resources):
def __init__(self):
self.response = resources.get_connect()
def get_details2(self):
print(self.response)
class Source3(resources):
def __init__(self):
self.response = resources.get_connect()
def get__detail3(self):
print(self.response)
source1 = Source1()
source2 = Source2()
source3 = Source3()
source1.get__details1()
source2.get_details2()
source3.get__detail3()
But the problem with the code is for every class in init method I am calling the get_connect method. I don't want to repeat the code. I need help for avoiding redundancy which I have asked below
Is there any way I can call get_connect in one place and use it for other classes maybe a decorator or anything? if yes how can I?
While creating objects also I am calling each class and calling each method every time. is there a way to use any design pattern here?
If anyone helps me with these oops concepts it will be useful.
First of all, is there any reason why you are using get_connect method as static?
Because what you can do here is declare it in the parent class:
class resources:
def __init__(self):
self.response = self.get_connect()
def get_connect(self):
return 1 + 2
This way you do not need to define the __init__ method on every class, as it will be automatically inherited from the parent.
Regarding the second question, it really depends on the context, but you can use a strategy pattern in order to retrieve the class that you require to call. For this rename the method of get details into the same for each of the classes, as basically they're used for the same purpose, but changed on the context of the class implementation:
class Source1(resources):
def get_details(self):
print(self.response)
class Source2(resources):
def get_details(self):
print(self.response)
class Source3(resources):
def get_details(self):
print(self.response)
classes = {
"source_1": Source1,
"source_2": Source2,
"source_3": Source3
}
source_class = classes["source_1"]
source = source_class()
source.get_details()
Hope this helped!

How can I run multiple definitions under a single class?

I am trying to create a class with several definitions (constructors?), however when I run the class it is only running the first def that I have written and not the second one, code example below:
class Test(baseline):
def test_1(self):
global caseid
caseid = xxx
global resultfail
resultfail = "Test Failed."
self.driver.get(self.base_url)
self.login()
print('Test 1')
self.Test1TestCase()
def test_2(self):
self.driver.get(self.base_url)
self.login()
print('Test 2')
self.Test2TestCase()
Could someone please advise what changes I need to make for the Class to run both definitions? Or if this is even possible under a single Class? Cheers.
In your class Test , I am assuming baseline is a super-class since you are defining class Test with it.
You haven't created a constructor that will help class instances to be established.
class Test(baseline):
def __init__(self):
#initialize something
Next, you need to call and instantiate Test class within main (outside class)
sampleTest = Test() #instance of Test
Then you can call "methods" (functions) within class Test as,
sampleTest.test_1()
sampleTest.test_2()
Hope this is what you are looking for.

How to inject mock objects into instance attributes in Python unit testing

I am learning python
I'm wondering if there is a mechanism to "inject" an object (a fake object in my case) into the class under test without explicitly adding it in the costructor/setter.
## source file
class MyBusinessClass():
def __init__(self):
self.__engine = RepperEngine()
def doSomething(self):
## bla bla ...
success
## test file
## fake I'd like to inkject
class MyBusinessClassFake():
def __init__(self):
pass
def myPrint(self) :
print ("Hello from Mock !!!!")
class Test(unittest.TestCase):
## is there an automatic mechanism to inject MyBusinessClassFake
## into MyBusinessClass without costructor/setter?
def test_XXXXX_whenYYYYYY(self):
unit = MyBusinessClass()
unit.doSomething()
self.assertTrue(.....)
in my test I'd like to "inject" the object "engine" without passing it in the costructor. I've tried few option (e.g.: #patch ...) without success.
IOC is not needed in Python. Here's a Pythonic approach.
class MyBusinessClass(object):
def __init__(self, engine=None):
self._engine = engine or RepperEngine()
# Note: _engine doesn't exist until constructor is called.
def doSomething(self):
## bla bla ...
success
class Test(unittest.TestCase):
def test_XXXXX_whenYYYYYY(self):
mock_engine = mock.create_autospec(RepperEngine)
unit = MyBusinessClass(mock_engine)
unit.doSomething()
self.assertTrue(.....)
You could also stub out the class to bypass the constuctor
class MyBusinessClassFake(MyBusinessClass):
def __init__(self): # we bypass super's init here
self._engine = None
Then in your setup
def setUp(self):
self.helper = MyBusinessClassFake()
Now in your test you can use a context manager.
def test_XXXXX_whenYYYYYY(self):
with mock.patch.object(self.helper, '_engine', autospec=True) as mock_eng:
...
If you want to inject it with out using the constuctor then you can add it as a class attribute.
class MyBusinessClass():
_engine = None
def __init__(self):
self._engine = RepperEngine()
Now stub to bypass __init__:
class MyBusinessClassFake(MyBusinessClass):
def __init__(self):
pass
Now you can simply assign the value:
unit = MyBusinessClassFake()
unit._engine = mock.create_autospec(RepperEngine)
After years using Python without any DI autowiring framework and Java with Spring I've come to realize plain simple Python code often doesn't need frameworks for dependency injection without autowiring (autowiring is what Guice and Spring both do in Java), i.e., just doing something like this is enough:
def foo(dep = None): # great for unit testing!
self.dep = dep or Dep() # callers can not care about this too
...
This is pure dependency injection (quite simple) but without magical frameworks for automatically injecting them for you (i.e., autowiring) and without Inversion of Control.
Unlike #Dan I disagree that Python doesn't need IoC: Inversion of Control is a simple concept that the framework takes away control of something, often to provide abstraction and take away boilerplate code. When you use template classes this is IoC. If IoC is good or bad it is totally up to how the framework implements it.
Said that, Dependency Injection is a simple concept that doesn't require IoC. Autowiring DI does.
As I dealt with bigger applications the simplistic approach wasn't cutting it anymore: there was too much boilerplate code and the key advantage of DI was missing: to change implementation of something once and have it reflected in all classes that depend on it. If many pieces of your application cares on how to initialize a certain dependency and you change this initialization or wants to change classes you would have to go piece by piece changing it. With an DI framework that would be way easier.
So I've come up with injectable a micro-framework that wouldn't feel non-pythonic and yet would provide first class dependency injection autowiring.
Under the motto Dependency Injection for Humans™ this is what it looks like:
# some_service.py
class SomeService:
#autowired
def __init__(
self,
database: Autowired(Database),
message_brokers: Autowired(List[Broker]),
):
pending = database.retrieve_pending_messages()
for broker in message_brokers:
broker.send_pending(pending)
# database.py
#injectable
class Database:
...
# message_broker.py
class MessageBroker(ABC):
def send_pending(messages):
...
# kafka_producer.py
#injectable
class KafkaProducer(MessageBroker):
...
# sqs_producer.py
#injectable
class SQSProducer(MessageBroker):
...
Be explicit, use a setter. Why not?
class MyBusinessClass:
def __init__(self):
self._engine = RepperEngine()
from unittest.mock import create_autospec
def test_something():
mock_engine = create_autospec(RepperEngine, instance=True)
object_under_test = MyBusinessClass()
object_under_test._engine = mock_engine
Your question seems somewhat unclear, but there is nothing preventing you from using class inheritance to override the original methods. In that case the derivative class would just look like this:
class MyBusinessClassFake(MyBusinessClass):
def __init__(self):
pass

Mocking render to response with Pyramid

I have a decorator that looks like so:
def validate_something(func):
def validate_s(request):
if request.property:
render_to_response('template.jinja', 'error'
return func(request)
return validate_something
I'm trying to test it like so. I load the local WSGI stack as an app.
from webtest import TestApp
def setUp(self):
self.app = TestApp(target_app())
self.config = testing.setUp(request=testing.DummyRequest)
def test_something(self):
def test_func(request):
return 1
request = testing.DummyRequest()
resp = validate_something(test_func(request))
result = resp(request)
The error I'm getting is (being generated at the innermost render_to_response):
ValueError: no such renderer factory .jinja
I understand that I need to mock render_to_response, but I'm at a bit of a loss as to how to exactly do that. If anyone has any suggestions, I would greatly appreciate it.
Mock library is awesome:
mock provides a core Mock class removing the need to create a host of
stubs throughout your test suite. After performing an action, you can
make assertions about which methods / attributes were used and
arguments they were called with. You can also specify return values
and set needed attributes in the normal way.
Additionally, mock provides a patch() decorator that handles patching
module and class level attributes within the scope of a test
Youc code would look like this:
def test_something(self):
test_func = Mock.MagicMock(return_value=1) # replaced stub function with a mock
request = testing.DummyRequest()
# patching a Pyramid method with a mock
with mock.patch('pyramid.renderers.render_to_response' as r2r:
resp = validate_something(test_func(request))
result = resp(request)
assert r2r.assert_called_with('template.jinja', 'error')
The following worked for me:
def setUp(self):
self.app = TestApp(target_app())
self.config = testing.setUp(request=testing.DummyRequest)
self.config.include('pyramid_jinja2')
By setting up the config to include jinja your tests can then find your template and the jinja environment. You may also need to provide a test version of the template in the same folder as your tests. If you get a message such as TemplateNotFound on running the tests then make sure a version of the template is located in the correct place.

Categories

Resources