How to write python unittest for column name is a string? - python

I am not if this is right to but, I have this so far and I am trying to write unittest for this.
def ValidateInputs(self, class_column_name,):
class_column_name_ok = type(class_column_name) is str
if not class_column_name_ok:
raise(TypeError("Argument class_column_name must be a string type"))
I did this for this unittest but again with not having enough knowledge I am not sure. Any help will be much appreciated
def testClassColumnName(self):
self.assertTrue(type(class_column_name), "str")

Without knowing what you do with these values, I can't say 100%. I'll assume you bind them to the class, then provide the unittests I'd write.
Application code:
class MyClass(object):
"""This is my object, this is what it does"""
def validate_inputs(self, merge_columns, class_column_name):
"""some handy docstring"""
if not isinstance(class_column_name, str):
raise TypeError('Argument class_column_name must be a string, supplied {0}'.format(type(class_column_name))
self.class_column_name = class_column_name
unittests (using unittest form the stdlib):
import unittest
class TestMyClass(unittest.TestCase):
def setUp(self):
self.myclass = MyClass() # cheap way to always have a 'clean class' for testing
def test_validate_input_type_string(self):
"""Happy path test when input is correct, and everything works"""
self.myclass.validate_input(merge_columns='some-columns', class_column_name='some_column_name')
self.assertEqual(True, isinstance(self.myclass.class_column_name, str))
def test_validate_input_raises_typerror(self):
"""We raise TypeError if input != string"""
self.assertRaises(TypeError,
self.myclass.validate_input,
merge_columns=1234,
class_column_name=4321)
if __name__ == '__main__':
unittest.main()
General tips for unittesting:
A) Use self.assertEqual(A, B) -> the output on failure will give you some clue on why it failed. Using something like self.assertTrue normaly just outputs an error message like "False is not True"; which is, while 100% accurate, not very useful.
B) Supplying all positional args as key-word args -> makes reading the test later easier.
C) One assert per test case (two at the very most) -> more than this tends to get your test code too complex. Test should be so simple that anyone (even that intern that was just hired from a 3 month coding bootcamp) can figure them out. It's really painful to rewrite a hole test suite (or spend hours updating test code) b/c of a 10 minute update to application code.
Hope this is helpful.

Related

Is it possible to make pytest report if a function is never called directly in a test?

Example
def main(p):
if foo_a(p):
return False
return p**2
def foo_a(p):
return p % 11 == 0
Now you can get 100% test coverage by
import unittest
from script import main
class Foobar(unittest.TestCase):
def test_main(self):
self.assertEquals(main(3), 9)
But maybe one wanted foo_a to be p % 2 == 0 instead.
The question
Branch coverage would shed a light on it, but I would also like to know if a function was never called "directly" by a test (such as main is in the example), but only indirectly (such as foo_a in the example).
Is this possible with pytest?
First of all just general line of thought is to unittest foo_a as well
import unittest
from script import main, foo_a
class Foobar(unittest.TestCase):
def test_main(self):
self.assertEquals(main(3), 9)
def test_foo_a(self):
self.assertEquals(foo_a(11), True)
You are probably looking for https://coverage.readthedocs.io/en/coverage-4.5.1/ which can be used with pytest https://pypi.org/project/pytest-cov/, this tool can show you exactly which lines of code had been called during testing
But I think there is another way to check your problem it is called mutation testing, here are some libraries that could help you with it
https://github.com/sixty-north/cosmic-ray
https://github.com/mutpy/mutpy
And also look into property based testing libraries like https://github.com/HypothesisWorks/hypothesis/tree/master/hypothesis-python

Python: how to create a positive test for procedures?

I have a class with some #staticmethod's that are procedures, thus they do not return anything / their return type is None.
If they fail during their execution, they throw an Exception.
I want to unittest this class, but I am struggling with designing positive tests.
For negative tests this task is easy:
assertRaises(ValueError, my_static_method(*args))
assertRaises(MyCustomException, my_static_method(*args))
...but how do I create positive tests? Should I redesign my procedures to always return True after execution, so that I can use assertTrue on them?
Without seeing the actual code it is hard to guess, however I will make some assumptions:
The logic in the static methods is deterministic.
After doing some calculation on the input value there is a result
and some operation is done with this result.
python3.4 (mock has evolved and moved over the last few versions)
In order to test code one has to check that at least in the end it produces the expected results. If there is no return value then the result is usually stored or send somewhere. In this case we can check that the method that stores or sends the result is called with the expected arguments.
This can be done with the tools available in the mock package that has become part of the unittest package.
e.g. the following static method in my_package/my_module.py:
import uuid
class MyClass:
#staticmethod
def my_procedure(value):
if isinstance(value, str):
prefix = 'string'
else:
prefix = 'other'
with open('/tmp/%s_%s' % (prefix, uuid.uuid4()), 'w') as f:
f.write(value)
In the unit test I will check the following:
open has been called.
The expected file name has been calculated.
openhas been called in write mode.
The write() method of the file handle has been called with the expected argument.
Unittest:
import unittest
from unittest.mock import patch
from my_package.my_module import MyClass
class MyClassTest(unittest.TestCase):
#patch('my_package.my_module.open', create=True)
def test_my_procedure(self, open_mock):
write_mock = open_mock.return_value.write
MyClass.my_procedure('test')
self.assertTrue(open_mock.call_count, 1)
file_name, mode = open_mock.call_args[0]
self.assertTrue(file_name.startswith('/tmp/string_'))
self.assertEqual(mode, 'w')
self.assertTrue(write_mock.called_once_with('test'))
If your methods do something, then I'm sure there should be a logic there. Let's consider this dummy example:
cool = None
def my_static_method(something):
try:
cool = int(something)
except ValueError:
# logs here
for negative test we have:
assertRaises(ValueError, my_static_method(*args))
and for possitive test we can check cool:
assertIsNotNone(cool)
So you're checking if invoking my_static_method affects on cool.

unit testing protected class methods in python?

I am trying to import a class, than test a method (production_warning) from that class by passing in values 'stage', 'prod' to see if it returns the expected results.
import runner
test=runnerData(force_redeploy=False, pfactor=None, preview=True)
def production_warning_test():
assert.test.production_warning('stage') not errors
assert.test.production_warning('prod') contains "warning"
#run unit test
productionwarningtest()
I am clearly using assert completely wrong here, how do I properly accomplish what I'm trying to do with assert.
To do this with asserts, you'd want to change your assert statements to something like:
assert test.production_warning('stage') is not errors
assert test.production_warning('prod') contains "warning"
I'd highly recommend looking into the python unit test module instead though.
In which case you'd want something like this (note runnerData will need to be in scope, I'm just copying from your question above):
import runner
import unittest
class TestRunner(unittest.TestCase):
def setUp(self):
self.test = runnerData(force_redeploy=False, pfactor=None, preview=True)
def test_production_warning(self):
self.assertTrue(self.test.production_warning('stage') is not errors)
self.assertTrue(self.test.production_warning('prod') contains "warning")
if __name__ == '__main__':
unittest.main()

A DRY way of writing similar unit tests in python

I have some similar unit tests in python.
There are so similar that only one argument is changing.
class TestFoo(TestCase):
def test_typeA(self):
self.assertTrue(foo(bar=TYPE_A))
def test_typeB(self):
self.assertTrue(foo(bar=TYPE_B))
def test_typeC(self):
self.assertTrue(foo(bar=TYPE_C))
...
Obviously this is not very DRY, and if you have even 4-5 different options the code is going to be very repetitive
Now I could do something like this
class TestFoo(TestCase):
BAR_TYPES = (
TYPE_A,
TYPE_B,
TYPE_C,
...
)
def _foo_test(self, bar_type):
self.assertTrue(foo(bar=bar_type))
def test_foo_bar_type(self):
for bar_type in BAR_TYPES:
_foo_test(bar=bar_type))
Which works, however when an exception gets raised, how will I know whether _foo_test failed with argument TYPE_A, TYPE_B or TYPE_C ?
Perhaps there is a better way of structuring these very similar tests?
What are you trying to do is essentially a parameterized test. This feature isn't included in standard django or python unittest modules, but a number of libs provide it: nose-parameterized, py.test, ddt
My favorite so far is ddt: it resembles NUnit-JUnit style parameterized tests most, pretty lightweight, don't get in your way and does not require dedicated test runner (like nose-parameterized do). The way it can help you is that it modifies test name to include all parameters, so you would clearly see which test case failed by looking at a test name.
With ddt your example would look like this:
import ddt
#ddt.ddt
class TestProcessCreateAgencyOfferAndDispatch(TestCase):
#ddt.data(TYPE_A, TYPE_B, TYPE_C)
def test_foo_bar_type(self, type):
self.assertTrue(foo(bar=type))
In such case names will look like test_foo_bar_type__TYPE_A (technically, it constructs it something like [test_name]__[repr(parameter_1)]__[repr(parameter_2)]).
As a bonus, it is much cleaner (no helper method), and you get three methods instead of one. The advantage here is that you can test various code paths in a method and get one test case per each path (but a certain amount of thinking is needed, sometimes it's better to have a dedicated test for some of code paths)
Most TestCase assertion methods, including assertTrue, take an optional msg argument.
If you change your BAR_TYPES tuple to include the variable names, then you can include this in the message that is shown when the assertion fails.
class TestProcessCreateAgencyOfferAndDispatch(TestCase):
BAR_TYPES = (
('TYPE_A', TYPE_A),
('TYPE_B', TYPE_B),
('TYPE_C', TYPE_C),
...
)
def _foo_test(self, var_name, bar_type):
self.assertTrue(foo(bar=bar_type), var_name)
def test_foo_bar_type(self):
for (var_name, bar_type) in BAR_TYPES:
_foo_test(bar=bar_type), var_name=var_name)

python 2.6. unittest framework, asserts: help required

I am writing a test suite in python 2.6 using the unittest framework, and I want to use asserts in my code. I know that asserts got a complete overhaul and are much nicer in 2.7+ but I am confined to using 2.6 for now.
I am having problems using asserts. I want to be able to use the assertIn(a,b) feature, but alas, that is only in 2.7+. So I realized I must use the assertTrue(x) which is also in 2.6, but that didn't work. Then, I looked at this document which says that in previous versions assertTrue(x) used to be failUnless(x), so I used that in my code, and still no results.
I get the message:
NameError: global name 'failUnless' is not defined
which is the same thing I got for assertIn(a,b) and for assertTrue(x).
So I am totally at a loss for what I should do.
shorter version of my problem:
I want to be able to implement assertIn(a,b) in python 2.6.
Anyone have any solutions to this?
my code:
import unittest
class test_base(unittest.TestCase):
# some functions that are used by many tests
class test_01(test_base):
def setUp(self):
#set up code
def tearDown(self):
#tear down code
def test_01001_something(self):
#gets a return value of a function
ret = do_something()
#here i want to check if foo is in ret
failUnless("foo" in ret)
edit: Seems I am an idiot. All I needed to do was add self.assert.... and it worked.
import unittest
class MyTest(unittest.TestCase):
def test_example(self):
self.assertTrue(x)
This should work, based on the docs for unittest from Python 2.6. Be sure to use it as TestCase.assertTrue().
edit: In your example, set it as self.failUnless("foo" in ret) and it should work.
assertTrue should work just fine for an in test:
self.assertTrue('a' in somesequence)
All assertIn does is run the same test as above and set a helpful message if the test fails.
Your code for test case really helped.
Your problem is that you're trying to use assert[Something] as functions, while they're methods of TestCase class.
So you can solve your problem with, e.g. assertTrue:
self.assertTrue(element in list_object)
Actually implementing assertIn is pretty trivial. This is what I've used in my unit tests:
class MyTestCase(unittest.TestCase)
def assertIn(self, item, iterable):
self.assertTrue(item in iterable,
msg="{item} not found in {iterable}"
.format(item=item,
iterable=iterable))
You can then base all your testcases on this class instead unittest.TestCase and safely use assertIn even on python 2.6 and the error message will be much better than pure assertTrue. For comparison actual implementation of assertIn from Python 2.7:
def assertIn(self, member, container, msg=None):
"""Just like self.assertTrue(a in b), but with a nicer default message."""
if member not in container:
standardMsg = '%s not found in %s' % (safe_repr(member),
safe_repr(container))
self.fail(self._formatMessage(msg, standardMsg))

Categories