Running python function in ansible - python

python script test.py:
class Test:
def __init__(self):
pass
def addition(self, a, b):
return a + b
Below is the ansible playbook to execute Python script.
---
- name: execute install script
script: test.py
Instead of calling complete python script, Is it possible to call only addition method in test.py during ansible playbook execution

I do not think that this is possible. If test.py contains many classes, you can do the following, which will only define one class and never instanciate it.
from test import Test
print(Test.addition(None, 3, 4)) # prints 7
Why putting your function as a class method if you want to import it alone though ?
You could also do the following:
test.py
class Test:
def __init__(self):
pass
# Define function outside class so that it can be imported
def addition(self, a, b):
return a + b
# Add function to class
Test.addition = addition
And then do from test import addition

Related

How to verify when an unknown object created by the code under test was called as expected (pytest) (unittest)

I have some code that creates instances from a list of classes that is passed to it. This cannot change as the list of classes passed to it has been designed to be dynamic and chosen at runtime through configuration files). Initialising those classes must be done by the code under test as it depends on factors only the code under test knows how to control (i.e. it will set specific initialisation args). I've tested the code quite extensively through running it and manually trawling through reams of output. Obviously I'm at the point where I need to add some proper unittests as I've proven my concept to myself. The following example demonstrates what I am trying to test:
I would like to test the run method of the Foo class defined below:
# foo.py
class Foo:
def __init__(self, stuff):
self._stuff = stuff
def run():
for thing in self._stuff:
stuff = stuff()
stuff.run()
Where one (or more) files would contain the class definitions for stuff to run, for example:
# classes.py
class Abc:
def run(self):
print("Abc.run()", self)
class Ced:
def run(self):
print("Ced.run()", self)
class Def:
def run(self):
print("Def.run()", self)
And finally, an example of how it would tie together:
>>> from foo import Foo
>>> from classes import Abc, Ced, Def
>>> f = Foo([Abc, Ced, Def])
>>> f.run()
Abc.run() <__main__.Abc object at 0x7f7469f9f9a0>
Ced.run() <__main__.Abc object at 0x7f7469f9f9a1>
Def.run() <__main__.Abc object at 0x7f7469f9f9a2>
Where the list of stuff to run defines the object classes (NOT instances), as the instances only have a short lifespan; they're created by Foo.run() and die when (or rather, sometime soon after) the function completes. However, I'm finding it very tricky to come up with a clear method to test this code.
I want to prove that the run method of each of the classes in the list of stuff to run was called. However, from the test, I do not have visibility on the Abc instance which the run method creates, therefore, how can it be verified? I can't patch the import as the code under test does not explicitly import the class (after all, it doesn't care what class it is). For example:
# test.py
from foo import Foo
class FakeStuff:
def run(self):
self.run_called = True
def test_foo_runs_all_stuff():
under_test = Foo([FakeStuff])
under_test.run()
# How to verify that FakeStuff.run() was called?
assert <SOMETHING>.run_called, "FakeStuff.run() was not called"
It seems that you correctly realise that you can pass anything into Foo(), so you should be able to log something in FakeStuff.run():
class Foo:
def __init__(self, stuff):
self._stuff = stuff
def run(self):
for thing in self._stuff:
stuff = thing()
stuff.run()
class FakeStuff:
run_called = 0
def run(self):
FakeStuff.run_called += 1
def test_foo_runs_all_stuff():
under_test = Foo([FakeStuff, FakeStuff])
under_test.run()
# How to verify that FakeStuff.run() was called?
assert FakeStuff.run_called == 2, "FakeStuff.run() was not called"
Note that I have modified your original Foo to what I think you meant. Please correct me if I'm wrong.

how to run the static method with each test

I have a function where I clean the database and reports. I would like to run this function every time I run tests (questions), regardless of whether I run one test (a method from the class) or the whole class.
My script is a static method
#staticmethod
def startScript():
removeData()
removeReport()
My example test:
test.py
class myTesting(unittest.TestCase):
def test_add_new_user(self, name, elem1, elem2):
code my test.
how to add a script to run it every time you run tests? Thank you for your help
add it as a fixture to your functions
https://docs.pytest.org/en/latest/fixture.html
#pytest.fixture
def startScript():
removeData()
removeReport()
or add it to your setup_method in class:
def setup_method(self, method):
startScript();
a third way:
add the static function to the conftest.py of the scope, this file should be in the same level as test.py :
#pytest.fixture(autouse=True, scope='function'):
def startScript():
removeData()
removeReport()
more info on conftest.py:
https://docs.pytest.org/en/2.7.3/plugins.html?highlight=re

Using Python's UnitTest Mock for a new Object

I'm trying to learn how to use Mocks for Python. However I've been struggling with some basic application of it.
Let's say our piece of code that I want to test is this:
class ProductionClass:
def method(self):
newone=ProductionClass()
newone.something(1, 2, 3)
def something(self, a, b, c):
pass
def __init__(self):
print("Test")
Which have a method which is simply create a new object of itself and calls a method of that class.
import unittest
import unittest.mock
from ProductionClass import *
from unittest.mock import *
class TestProduction(unittest.TestCase):
def test_one(self):
real = ProductionClass()
real.something = MagicMock()
real.method()
real.something.assert_called_once_with(1, 2, 3)
if __name__ == '__main__':
unittest.main()
Once again, this is a very simple UnitTest, basically copypasted from 26.5.1.1 of https://docs.python.org/3/library/unittest.mock-examples.html .
However, this would test if real.something has been called, meanwhile the one i really want to test is if newone.something has been called.
Considering newone is created later when we actually call method()-method how do I use mock to test it?
You can test this by simply instantiate ProductionClass in setUp method and patch ProductionClass in test_one as follows
import unittest
import ProductionClass
import mock
class TestProduction(unittest.TestCase):
def setUp(self):
self.real = ProductionClass.ProductionClass()
#mock.patch("ProductionClass.ProductionClass")
def test_one(self, mock1):
print "From Test : %s " % mock1()
real = self.real
real.method()
mock1().something.assert_called_once_with(1, 2, 3)
if __name__ == '__main__':
unittest.main()
I just modified the production class to show that both object refers to the same instance of the mock
class ProductionClass:
def method(self):
newone=ProductionClass()
print "From Production class : %s" % newone
newone.something(1, 2, 3)
def something(self, a, b, c):
pass
def __init__(self):
print("Test")
Output:
Testing started at 5:52 PM ...
Test
From Test : <MagicMock name='ProductionClass()' id='4330372048'>
From Production class : <MagicMock name='ProductionClass()' id='4330372048'>
Process finished with exit code 0
You can verify that both object refers the same instance of the mock object by looking the id
PS: I've been using mock package for this example so you probably need to install it using pip.

Dynamically call a method from a list of Python classes/objects

I have X number of python classes that all inherit from the same abstract base class, which expects children to implement a single method called executeTest()
Class TestCase:
def executeTest():
#do some logic for the test, then return if it passed or failed
In my main program I need to load an instance of each class that inherits this base class one at a time, call executeTest(), and record the result into some sort of collection for later use. The number of classes that implement TestCase will continue to grow over time, as people think up new tests to write.
How can I do this efficiently in python? Do I need to have a separate XML or similar type file which has a list of all individual class names, and then use some sort of class loading function inside a for loop? This is my first night coding in python so I'm not even really sure what techniques or keywords to search for.
This is a meta answer - which means that I think that you should think about your design calling tests.
In python there are well established ways to write tests. [1]
And there are also tools which collect all the available tests and executes them (including stats, coverage, xml output, ...). [2]
If I were you I would have a look at them. If you can use them, there is no need to re-invent the wheel.
[1] http://docs.python.org/library/unittest.html
[2] http://readthedocs.org/docs/nose/en/latest/
Use a decorator to enumerate the classes, and execute the methods with a list comprehension.
I will try to do it this way:
1) Save your abstract class in test_case.py
class TestCase:
def executeTest():
#do some logic for the test, then return if it passed or failed
2) Save all your child classes in in test_case_children.py
from test_case import TestCase
class Test_Case_1(TestCase):
def executeTest():
#overriden function
class Test_Case_2(TestCase):
def executeTest():
#overriden function
class Test_Case_3(TestCase):
def executeTest():
#overriden function
3) Save main function in main.py:
from test_case import TestCase
import test_case_children
def main():
#grab the all the elements in the script 'test_case_children'
items = test_case_children.__dict__
#build list of all 'TestCase' sub-classes
test_classes = []
for (key, value) in items.items():
try:
# check whether the item is a sub-class of 'TestCase' class
if TestCase.__subclasscheck__(value):
test_classes.append(value)
except TypeError: #if item is not of type 'TestCase', ignore it
pass
#run the tests
for test_class in test_classes:
test_runner = test_class()
test_runner.executeTest()
# this will run main() method, only when script is directly executed
# from shell or command prompt ...
if __name__ == "__main__":
main()
4) Execute the main.py script:
$ python main.py
Note: One more thing, the folder in which you will save these files should also contain an empty __init__.py file to make that folder as python app(something like packages in Java or namespaces in C++). If you don't then those import statements will not work, probably.
[ Update for running test_cases from different files ]
1) Keep the files in following heirarchy:
<root>/
------>test_case/
---------------->__init__.py
---------------->main.py
---------------->test_case.py
---------------->test_case_children/
--------------------------------->__init__.py
--------------------------------->test_case_1.py
--------------------------------->test_case_2.py
--------------------------------->test_case_3.py
2) Save your abstract class in test_case/test_case.py
class TestCase:
def executeTest():
#do some logic for the test, then return if it passed or failed
3) Save sub-classes like this:
File: test_case/test_case_children/test_case_1.py
from test_case.test_case import TestCase
class Test_Case_1(TestCase):
def executeTest():
#overriden function
File: test_case/test_case_children/test_case_2.py
from test_case.test_case import TestCase
class Test_Case_2(TestCase):
def executeTest():
#overriden function
File: test_case/test_case_children/test_case_3.py
from test_case.test_case import TestCase
class Test_Case_3(TestCase):
def executeTest():
#overriden function
4) Save main function in main.py:
from test_case import TestCase
from test_case import test_case_children
def main():
#grab the all the elements in the module 'test_case_children'
items = test_case_children.__dict__
#build list of all 'TestCase' sub-classes
test_classes = []
for (dict_key, dict_value) in items:
#check whether the type of item's value is a module,
# if its a module it's likely to contain a TestCase subclass...
if str(type(dict_value)) == "<type 'module'>":
for (key, value) in dict_value.items():
try:
# check whether the item is a sub-class of 'TestCase' class
if TestCase.__subclasscheck__(value):
test_classes.append(value)
except TypeError: #if item is not of type 'TestCase', ignore it
pass
#run the tests
for test_class in test_classes:
test_runner = test_class()
test_runner.executeTest()
# this will run main() method, only when script is directly executed
# from shell or command prompt ...
if __name__ == "__main__":
main()
5) Execute the main.py script:
$ cd test_case/
$ python main.py
I hope this would work for you.

Previewing the class or function definition source code in the interactive shell

Is it possible to access a source code of the imported class or funciton while using interactive shell like IDLE Shell or Linux python?
In example, I wish that it was possible to do the following:
from myClasses import MyClass
#this
print MyClass.__source__
#or that
source(MyClasss)
# would result in:
def MyClass(object):
pass
from myClasses import MyClass
import inspect
source = inspect.getsource(MyClass)
print source
#class MyClass(object):
# pass

Categories

Resources