Everyone
I have a function which is the handler for aws lambdafunction.
def data_list(event, data_subject):
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("TestTable")
print("DATA_LIST")
def get_col_name(data_subject):
if data_subject == "X":
return 'something'
elif data_subject == "y":
return 'some other things'
elif data_subject == "c":
return 'really'
def another_function(var):
pass
I have multiple function under data_list function how can we write unittest cases for each individual function which is under data_list function
Don't.
Instead move them out from the lambda handler function so that you can test them entirely separately.
Then make the lambda handler function it's self so small and simple that you barely need to test it, and can handle testing it with system tests.
Related
How do I write multiple test cases for a single function. I want the functions to essentially iterate through a bunch of tests and then return a boolean or answer saying that the function has passed these tests.
def test_valid01():
name = 'jack'
expected = True
assert is_valid_name(name) == expected, "is_valid_name has failed."
test1 = True
this is an example of one of my functions testing another function.
A way that you could test various tests for the is_valid_name() function:
def assert_test_valid(name, expected_value):
assert is_valid_name(name) == expected_value, f"is_valid_name has failed for {name}" # allows identification of which test failed
def test_valid_all():
test_responses = { # the input and the expected response
'jack': True,
}
for key, value in test_responses.items(): # to go through all of the responses that you would like to test
assert_test_valid(key, value)
Is it possible to somehow to have 2 functions with the same name, but only one of the gets defined.
Something like:
version='revA'
def RevA():
if (version=='revA'):
return lambda x: x
else:
return lambda x: None
def RevB():
if (version=='revB'):
return lambda x: x
else:
return lambda x: None
#RevA
def main():
print("RevA")
#RevB
def main():
print("RevB")
main()
How about classes and inheritance:
class Base:
def main(self):
print("base")
class RevA(Base):
def main(self):
print("RevA")
class RevB(Base):
def main(self):
print("RevB")
if version == 'revA':
obj = RevA()
elif version == 'revB:
obj = RevB()
else:
obj = Base()
obj.main()
Also typical are factory functions like:
def get_obj(version, *args, **kwargs):
omap = { 'revA': revA, 'revB': revB }
return omap[version](*args, **kwargs)
This allows you to call for example:
obj = get_obj('revA', 23, fish='burbot')
Which will be equivalent to:
if version == 'revA':
obj = revA(23, fish='burbot')
You can, but doing literally that would be very uncommon:
if version == 'revA':
def main():
print("RevA")
elif version == 'revB':
def main():
print("RevB")
main()
More usually, you'd define both functions then choose which one to use by assigning it to a variable:
def main_A():
print("RevA")
def main_B():
print("RevB")
# select the right version using a dispatch table
main = {
'RevA': main_A,
'RevB': main_B,
}[version]
main()
Variants of this latter approach are quite common; both web applications and graphical applications often work this way, with a table mapping URLs or user actions to functions to be called. Often the table is maintained by the framework and your code adds entries to it in multiple places in the code, sometimes in bulk (eg Django), sometimes one by one (eg Flask).
Having both functions defined (not just the selected one) means that you can also call each version directly; that's useful if the main program uses a dispatch table but various subsidiary code (such as the tests) needs to call a particular one of the functions
def publish_book(publisher):
# some calculations
factor = 4
print('xyz')
db_entry(factor) # db entry call which I want to mock
print('abc')
def update():
publish_book('xyz')
#pytest.mark.django_db
def test_update(mocker):
# in here I'm unable to mock nested function call
pass
I have db_entry() function call in publish_book(). how can we mock db_entry() function call inside publish_book.I want to perform other calculations of publish_book(), but only skip(mock) the db_entry() call.
You can use monkeypatch to mock functions. Here is an example if it helps you.
def db_entry():
return True
def add_num(x, y):
return x + y
def get_status(x, y):
if add_num(x, y) > 5 and db_entry() is True:
return True
else:
return False
def test_get_stats(monkeypatch):
assert get_status(3, 3)
monkeypatch.setattr("pytest_fun.db_entry", lambda: False)
assert not get_status(3, 3)
As you can see before doing the second assertion i am mocking the value of db_entry function to return false. You can use monkeypatch to mock the function to return nothing if you want by using lambda like lambda: None
I am not sure what your db_entry function does but say it is doing some db query and returning list of results you can mock that also using lambda by returning lambda: ["foobar"]
I have a utility function that takes the argument case and return the value accordingly
helper.py
def get_sport_associated_value(dictionary, category, case):
if case == 'type':
return "soccer"
else:
return 1 #if case = 'id'
I have a main function that use the above function
crud_operations.py
def get_data(category):
dictionary ={.....}
id = get_sport_associated_value(dictionary, category, 'id')
.....
.....
type = get_sport_associated_value(dictionary, category, 'type')
....
return "successful"
Now I am unittesting the get_data() module using the unittest.Mock. I am having trouble passing the values to id and type.
#mock.patch('helper.get_sport_associated_value')
def test_get_data(self, mock_sport):
with app.app_context():
mock_sport.side_effect = self.side_effect
mock_sport.get_sport_associated_value("id")
mock_sport.get_sport_associated_value("type")
result = get_queries("Soccer")
asserEquals(result, "successful")
def side_effect(*args, **kwargs):
if args[0] == "type":
print("Soccer")
return "Soccer"
elif args[0] == "id":
print("1")
return 1
I tried this using side_effect function and facing problem to mock the get_sport_associated_value() according to the different values of input argument.
Question 2 : Which is the best method to use mock or mock.magicmock in this scenario?
Any help is appreciated with unit testing
Thanks
You're incorrectly testing args[0] as a case. The arguments of the side_effect callback function should be the same as the function you want to mock:
def side_effect(dictionary, category, case):
if case == "type":
return "Soccer"
elif case == "id":
return 1
Hi im doing a udacity course on testing and I dont understand why im getting this problem with globals.
The thing is there is some implementation of queue I want to test. To do so I wrapp the methods with the post conditions [empty, full,enqueue,dequeue] using asserts and then proceed to do a random test on the structure with the wrapped functions to automate the testing.
For the assertions I need to keep track of the max items (size) of the queue and the actual items (elts) so i defined them as locals in function test().
Inside test() i define the wrapers and in the wrappers i use size and elts.
The thing i dont understand is if i make elts global inside the wrapper definition, then i got a NameError global name 'elts' is not defined at the wrapper But if i dont declare it as global in the wrapper then i get the UnboundLocalError of accessing elts before assigning a value to it.
I dont understand why a "Son" function declared in the body of a "Father" function cant see a local variable of the father and use it.
Here is the code
from queue_test import *
import random
import sys
def test():
# Globals
iters=100
max_int=sys.maxint
min_int=1
elts=0
size=0
#Queue wrappers
# Wrapp the queue methods to include the assertions for automated testing
def run_empty():
temp=q.empty()
if elts==0:
assert temp==True
else:
assert temp==False
return temp
def run_full():
temp=q.full()
if elts==size:
assert temp==True
else:
assert temp==False
return temp
def run_enqueue(val):
temp=q.enqueue(val)
if isinstance(val,int) and elts<size:
elts+=1
assert temp==True
else:
assert temp==False
return temp
def run_dequeue():
temp=q.dequeue()
if elts>0:
elts-=1
assert temp!=None and isinstance(temp,int)
else:
assert temp==None
return temp
# Random testing stuff
def get_int(): # Return a random valid integer
return random.randint(min_int,max_int)
def get_command(): #Return a random valid command (string)
return random.choice(["empty","full","enqueue","dequeue"])
def run_random_command(): # Execute a random command
c=get_command()
if c=="empty":
run_empty()
elif c=="full":
run_full()
elif c=="enqueue":
run_enqueue(get_int())
elif c=="dequeue":
run_dequeue()
else:
raise Exception("Error run command invalid command")
def test_this(ncommands=100): # Randomly test a queue with ncommands commands
run_empty()
testi=get_int()
run_enqueue(testi)
testi2=run_dequeue()
assert testi == testi2
for c in range(ncommands):
run_random_command()
#Test Code: Do it random tests each one with a diferent random queue
for it in range(iters):
size=get_int()
elts=0
q=Queue(size)
test_this()
If you assign to a variable within a function, Python automatically makes it local. You'll need to explicitly mark them as global within the child functions. (In Python 3, you can use nonlocal for that.)
However, I can't help thinking that you should really be using a class here.