I'm struggling to create a unit test, if someone could please have a look on my code to figure out the possible issue: - unit-testing

The code below is supposed to simulate a ATM, I have to create 5 unit tests for the code, and to be honest I have no idea why it is not working! :(
It should show on the Terminal that ran 5 tests in x s, however it keeps saying that Ran 0 tests and OK. Should I import a library? Any suggestion?
import unittest
def withdraw(wdra):
balanace_account = 100
if wdra < balanace_account:
balanace_account -= wdra
return balanace_account
class AtmTest(unittest.TestCase):
def correct_amount(self):
expected = 29.50 #withdraw de 70.50
result = withdraw(70.5)
self.assertEqual(expected,result)
def invalid_error(self):
expected = 1
result = withdraw(1/0)
self.assertEqual(expected, result)
def incorrect_amount(self):
expected = 50.00
result = withdraw(60)
self.assertEqual(expected,result)
def greater_withdraw(self):
expected = -10
result = withdraw(110)
self.assertEqual(expected,result)
def invalid_data_type(selfS):
expected = 100
result = withdraw('0')
self.assertEqual(expected, result)
if __name__ == '__main__':
unittest.main()
pass

You should name your test methods with test prefix so that the test runner can identify test methods. See here for example.

Related

In pytest returns magicMock instance instead of return value

i have a sample method and a pytest method for it.
import pytest
from datetime import datetime
# this is the method to test
def get_time_of_day():
"""return string Night/Morning/Afternoon/Evening depending on the hours range"""
time = datetime.now()
print(time.hour)
if 0 <= time.hour <6:
return "Night"
if 6 <= time.hour < 12:
return "Morning"
if 12 <= time.hour <18:
return "Afternoon"
return "Evening"
#pytest method, where I am trying to mock datetime.now
def test_get_time_of_day(mocker):
mock_now = mocker.patch("tests.test_sample.datetime")
mock_now.now.return_value = datetime(2016, 5, 20, 14, 10, 0)
assert get_time_of_day() == "Afternoon"
But when I try to run the pytest as follow
python3 -m pytest test_sample.py
I get TypeError: '<=' not supported between instances of 'int' and 'MagicMock'
I have a directory tests inside that I have the python file test_sample.py. In this file, I have written this code.
I have referred this page:
So do anyone Know to solve this issue. Thank you
This is because when you are assigning a value to mock_now.now.return_value, datetime is already patched and returns a MagicMock instead of the datetime object as you expect.
This would work:
def test_get_time_of_day(mocker):
dt = datetime(2016, 5, 20, 14, 10, 0)
mock_now = mocker.patch("tests.test_sample.datetime")
mock_now.now.return_value = dt
assert get_time_of_day() == "Afternoon"
As you would typically patch objects in modules that you test (instead of within the test module itself), you would not run into this issue.

Code run in my Jupyter notebook gives different results from same code I run using Flask

I wrote a neural network code in jupyter notebook. This is a snippet of the code:
import numpy
import matplotlib.pyplot
%matplotlib inline
import imageio
class neuralNetwork:
def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
self.wih = numpy.random.normal(0.0,pow(self.inodes,- 0.5),(self.hnodes,self.inodes))
self.who = numpy.random.normal(0.0,pow(self.hnodes,- 0.5),(self.onodes,self.hnodes))
self.activation_function = lambda x: scipy.special.expit(x)
self.lr = learningrate
pass
When I run it and test with my testing images, I get around 94% accuracy. I then created a flask application, and kept the above code in a .py file. I imported the code as:
from nn import neuralNetwork
Then I created instance an instance of the class and run the following code to train:
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes,learning_rate)
training_data_file = open("mnist_dataset/mnist_train.csv",'r')
training_data_list = training_data_file.readlines()
training_data_file.close()
epochs = 1
for e in range(epochs):
for record in training_data_list:
all_values = record.split(',')
inputs = (numpy.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
targets = numpy.zeros(output_nodes) + 0.01
targets[int(all_values[0])] = 0.99
n.train(inputs,targets)
pass
pass
Then I write the following code to test it:
test_data_list = test_data_file.readlines()
scorecard = []
a = 0
for record in test_data_list:
all_values = record.split(',')
correct_label = int(all_values[0])
inputs = (numpy.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
outputs = n.query(inputs)
label = numpy.argmax(outputs)
if(label == correct_label):
scorecard.append(1)
else:
scorecard.append(0)
pass
pass
scorecard_array = numpy.asarray(scorecard)
return str(scorecard_array.sum()/scorecard_array.size)
But I realised that the value of "scorecard" is always below 10. But when I run the same code in Jupyter notebook, I get a scoredcard value above 90. Please any help on how to fix this issue

How to mock a method on an object in a class?

I'm trying to figure out how to mock with one additional level of indirection - a method on an object in a class.
import serial
class MyClass(object):
def __init__(self, com_port, baudrate):
self.sp = serial.Serial(com_port, baudrate)
def do_something(self, data):
num_bytes_written = self.sp.write(data)
if num_bytes_written != len(data):
return -1
return 0
In testfile:
import mock
...
#mock.patch('serial.Serial', return_value='')
#mock.patch('serial.Serial.write', return_value=0)
def test_do_something_fails_on_bad_write(self, mock_write):
...
want = -1
dummy_data = b'123'
inst = myfile.MyClass('COM8', 115200)
got = c.do_something(dummy_data)
self.assertEqual(got, want)
Unit test solution:
serial.py:
class Serial(object):
def __init__(self, port, baudrate):
self.port = port
self.baudrate = baudrate
def write(self, data):
return 100
myclass.py:
import serial
class MyClass(object):
def __init__(self, com_port, baudrate):
self.sp = serial.Serial(com_port, baudrate)
def do_something(self, data):
num_bytes_written = self.sp.write(data)
if num_bytes_written != len(data):
return -1
return 0
test_myclass.py:
import unittest
from unittest import mock
import serial
import myclass
class TestMyClass(unittest.TestCase):
#mock.patch('myclass.serial.Serial')
def test_do_something_fails_on_bad_write(self, mock_Serial):
serial_instance = mock_Serial()
serial_instance.write.return_value = 1
want = -1
dummy_data = b'123'
c = myclass.MyClass('COM8', 115200)
got = c.do_something(dummy_data)
self.assertEqual(got, want)
serial_instance.write.assert_called_once_with(b'123')
#mock.patch('myclass.serial.Serial')
def test_do_something_success(self, mock_Serial):
serial_instance = mock_Serial()
serial_instance.write.return_value = 3
want = 0
dummy_data = b'123'
c = myclass.MyClass('COM8', 115200)
got = c.do_something(dummy_data)
self.assertEqual(got, want)
serial_instance.write.assert_called_once_with(b'123')
if __name__ == '__main__':
unittest.main()
unit test result with coverage report:
..
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
Name Stmts Miss Cover Missing
--------------------------------------------------------------------------
src/stackoverflow/61333922/myclass.py 9 0 100%
src/stackoverflow/61333922/serial.py 6 3 50% 3-4, 7
src/stackoverflow/61333922/test_myclass.py 25 0 100%
--------------------------------------------------------------------------
TOTAL 40 3 92%

Python: Mock Opening File, return Actual File

I need to test a call to gzip.open, but I need it to supply it with an actual test file with test data in it to read. I've seen several very similar questions, but none of them work as expected.
This is the code I'm testing:
with gzip.open(local_file_path,'r') as content:
for line in content:
try:
if line.startswith('#'):
continue
line_data = line.split('\t')
request_key = line_data[LINE_FORMAT['date']]
request_key += '-' + line_data[LINE_FORMAT['time']][:-3]
request_key += '-' + line_data[LINE_FORMAT['source_ip']]
if request_key in result.keys():
result[request_key] += 1
else:
result[request_key] = 1
num_requests += 1
except Exception, e:
print ("[get_outstanding_requesters] \t\tError to process line: %s"%line)
I think the problem is related to the issues discussed here because the code treats the file as an iterator, but none of the workarounds discussed have worked for me.
I've tried variations on this:
test_data = open('test_access_log').read()
m = mock.mock_open(read_data=test_data)
m.return_value.__iter__ = lambda self:self
m.return_value.__next__ = lambda self: self.readline()
with mock.patch('gzip.open', m):
with gzip.open('asdf') as f:
for i in f:
print i
Which results in:
TypeError: iter() returned non-iterator of type 'MagicMock'
I'm using Python 2.7. I'm tearing my hair out over this one. Is my only solution to forget trying to use an iterator (actual files can be very large, which is why I'm trying to avoid doing so?)
This is working:
import unittest
import mock
test_data = open('test_access_log').read()
m = mock.mock_open(read_data=test_data)
m.return_value.__iter__.return_value = test_data.splitlines()
with mock.patch('gzip.open', m):
with gzip.open('test_access_log') as f:
for i in f:
print i
Thanks to bash-shell.net

setting an attribute at create retrieves None value - Python

So I have an Article class that models the articles in a store. When I create a new article, I want it to have an EAN 13 code. So I initialize the article with a 12 digits code and use the check_ean13() funtion to retrieve the control digit. It works but seems like in any moment, when the object is created, rewrite the ean13 attribute and replaces it for None. Any ideas?
Main
if __name__ == "__main__":
# create article
art1 = Article("123456789087", "Article 1", 145.6, 200.0)
print art1
print art1.get_ean13()
class Article
class Article:
def __init__(self, cod, art_name, cost, listprice):
self.ean13 = self.set_ean13(cod)
self.art_name = art_name
self.cost = cost
self.listprice = listprice
self.commission = None
self.promotion=[]
def get_ean13(self):
return self.ean13
def set_ean13(self,cod):
cd = self.check_ean13(cod)
ean13 = cod + str(cd)
self.ean13=ean13
def check_ean13(self, code):
checksum = 0
for i, digit in enumerate(reversed(code)):
checksum += int(digit) * 3 if (i % 2 == 0) else int(digit)
return (10 - (checksum % 10)) % 10
output:
None - Article 1 list price: 400.0
None
self.ean13 = self.set_ean13(cod)
set_ean13 doesn't return anything, so you're effectively doing self.ean13 = None here. Just call the method without assigning the result.
self.set_ean13(cod)