How to write unit testing script using unittest - python

I want to write a unit test cases using unittest where my input is set of images and output is set of images with boundary box in the text, also it generate co-ordinate of the boundary boxes. How can I write test script for that using unittest pyunit framework.
So I have written unittest script to test api is working or not, response should be json / and list format and response of image file format should be png,jpg format, which is working now. I have below test case scenario need to test but how I will check? I don't know.
If optional keys are not passed to API, it should not throw an error. (opposite for compulsory ones) 8) The implemented route should throw/return error if GET request is passed instead of POST. 9) If valid path but invalid file name is provided, you should see respective error. 10) In case of invalid path, you should see respective error message. 11) There is specified set of keys which are compulsory to be passed to APIs, if not it returns an error 12) verify for session time out.
Here is my code:
import requests
import json
import sshtunnel
import unittest
class TestSequentialExecutions(unittest.TestCase):
def setUp(self) -> None:
a=10
def test_API(self):
self.resp_list = []
# API url
url = ['dummy url','dummyurl']
# Additional headers.
headers = {'Content-Type': 'application/json'}
# Body
payload = [{'input': 'dummy path'},
{"path": "dummy"}]
# Test case-1 checking valid API is routed or not
# convert dict to json by json.dumps() for body data.
for i in range(len(url)):
resp = requests.post(url[i], headers=headers, data=json.dumps(payload[i], indent=4))
self.assertEqual(resp.status_code, 200)
self.resp_list.append(resp.json())
#Test case-2 to check input file is in JPG ,PNG format or not
def test_fileformat(self):
n = len(self.resp_list[1])
my_list = [1]*n
empty_list=[]
extensions = ['png','v']
for filename in self.resp_list[0]:
if filename.lower().endswith(('.png', '.jpg')):
empty_list.append(1)
else:
empty_list.append(0)
self.assertEqual(my,empy_list)
if __name__ == '__main__':
unittest.main()
Actually I am trying to write test script for below github code: https://github.com/eragonruan/text-detection-ctpn

Related

Parse JSON answer

I have a response and I need the value of one parameter and I don't know how to parse it.
This is the response. I just need a hint to find out how to extract the data from this response and save it to one variable.
Then the next step is to show it, to prove that it gave me the activation code.
{"status":"created","statusCode":"0001","message":{"type":"success","text":"\xd8\xab\xd8\xa8\xd8\xaa\xe2\x80\x8c\xd9\x86\xd8\xa7\xd9\x85 \xd9\x85\xd9\x88\xd9\x81\xd9\x82\xdb\x8c\xd8\xaa \xd8\xa2\xd9\x85\xdb\x8c\xd8\xb2 \xd8\xa8\xd9\x88\xd8\xaf"},"error":[],"data":{"user":{"uuid":"f0dd5bee-2228-42a2-a832-ca577002496d","username":"droppp459","phoneNumber":"09443757689","activationCode":"73821"}}}'
And this is my code:
import requests
import json
import jsonpath
# Api
url = "http://dropp.dlinkddns.com:5000/api/users/register/complete"
def test_new_user():
# ReadFile
file = open("/Users/amirmarezloo/Downloads/Js.json")
json_input=file.read()
request_json=json.loads(json_input)
#Post
response=requests.post(url,request_json)
#Response
assert response.status_code==201
#Header
print(response.headers.get("Content-Type"))
#Parse
response_json=json.loads(response.text)
#Pick
Active=jsonpath.jsonpath(response_json,'activationCode')
print(response.content)
In this case, I would like to print on screen 73821 which is the activation code given in the response.
Use parse from jsonpath_ng ( pip install jsonpath-ng )
from jsonpath_ng import parse
jsonpathExp = parse("$..[*].activationCode")
match = jsonpathExp.find(response_json)
for item in match:
print(item.value,"\n")
Parsing contexts:
$ indicates the root object
. indicates next level
* indicates any field
[n] indicates list index

send data to html dashboard in python flask while having dictionary in a function parameter

I want to send data to html in flask framework, i have a function which receives dictionary as a parameter, then there are several functions applied on dictionary. after that final result i want to render in to html page. Its been 48 hours i am trying from different blogs but didn't get precise solution.
imports ...
from other file import other_functions
from other file import other_functions_2
from other file import other_functions_3
app = Flask(__name__, template_folder='templates/')
#app.route("/dashboard")
def calculate_full_eva_web(input:dict):
calculate_gap = other_functions(input)
calculate_matrix = other_functions_2(input)
average = other_functions_3(input)
data = dict{'calculate_gap':calculate_gap, 'calculate_matrix':calculate_matrix,'average':average}
return render_template('pages/dashboard.html', data = data)
if __name__ == "__main__":
app.run(debug=True)
TRACEBACK
Methods that Flask can route to don't take dictionaries as inputs, and the arguments they do take need to be matches by a pattern in the route. (See https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations)
You'd get the same error if you changed
#app.route("/dashboard")
def calculate_full_eva_web(input:dict):
to
#app.route("/dashboard")
def calculate_full_eva_web(input):
Your path forward depends on how you want to pass data when you make the request. You can pass key/value pairs via URL parameters and retrieve them via the request.args object. That might be close enough to what you want. (You'll need to remove the argument declaration from calculate_full_eva_web())
Something like
from flask import request
#app.route('/dashboard')
def calculate_full_eva_web():
input = request.args
...

Should I switch from "urllib.request.urlretrieve(..)" to "urllib.request.urlopen(..)"?

1. Deprecation problem
In Python 3.7, I download a big file from a URL using the urllib.request.urlretrieve(..) function. In the documentation (https://docs.python.org/3/library/urllib.request.html) I read the following just above the urllib.request.urlretrieve(..) docs:
Legacy interface
The following functions and classes are ported from the Python 2 module urllib (as opposed to urllib2). They might become deprecated at some point in the future.
2. Searching an alternative
To keep my code future-proof, I'm on the lookout for an alternative. The official Python docs don't mention a specific one, but it looks like urllib.request.urlopen(..) is the most straightforward candidate. It's at the top of the docs page.
Unfortunately, the alternatives - like urlopen(..) - don't provide the reporthook argument. This argument is a callable you pass to the urlretrieve(..) function. In turn, urlretrieve(..) calls it regularly with the following arguments:
block nr.
block size
total file size
I use it to update a progressbar. That's why I miss the reporthook argument in alternatives.
3. urlretrieve(..) vs urlopen(..)
I discovered that urlretrieve(..) simply uses urlopen(..). See the request.py code file in the Python 3.7 installation (Python37/Lib/urllib/request.py):
_url_tempfiles = []
def urlretrieve(url, filename=None, reporthook=None, data=None):
"""
Retrieve a URL into a temporary location on disk.
Requires a URL argument. If a filename is passed, it is used as
the temporary file location. The reporthook argument should be
a callable that accepts a block number, a read size, and the
total file size of the URL target. The data argument should be
valid URL encoded data.
If a filename is passed and the URL points to a local resource,
the result is a copy from local file to new file.
Returns a tuple containing the path to the newly created
data file as well as the resulting HTTPMessage object.
"""
url_type, path = splittype(url)
with contextlib.closing(urlopen(url, data)) as fp:
headers = fp.info()
# Just return the local path and the "headers" for file://
# URLs. No sense in performing a copy unless requested.
if url_type == "file" and not filename:
return os.path.normpath(path), headers
# Handle temporary file setup.
if filename:
tfp = open(filename, 'wb')
else:
tfp = tempfile.NamedTemporaryFile(delete=False)
filename = tfp.name
_url_tempfiles.append(filename)
with tfp:
result = filename, headers
bs = 1024*8
size = -1
read = 0
blocknum = 0
if "content-length" in headers:
size = int(headers["Content-Length"])
if reporthook:
reporthook(blocknum, bs, size)
while True:
block = fp.read(bs)
if not block:
break
read += len(block)
tfp.write(block)
blocknum += 1
if reporthook:
reporthook(blocknum, bs, size)
if size >= 0 and read < size:
raise ContentTooShortError(
"retrieval incomplete: got only %i out of %i bytes"
% (read, size), result)
return result
4. Conclusion
From all this, I see three possible decisions:
I keep my code unchanged. Let's hope the urlretrieve(..) function won't get deprecated anytime soon.
I write myself a replacement function behaving like urlretrieve(..) on the outside and using urlopen(..) on the inside. Actually, such function would be a copy-paste of the code above. It feels unclean to do that - compared to using the official urlretrieve(..).
I write myself a replacement function behaving like urlretrieve(..) on the outside and using something entirely different on the inside. But hey, why would I do that? urlopen(..) is not deprecated, so why not use it?
What decision would you take?
The following example uses urllib.request.urlopen to download a zip file containing Oceania's crop production data from the FAO statistical database. In that example, it is necessary to define a minimal header, otherwise FAOSTAT throws an Error 403: Forbidden.
import shutil
import urllib.request
import tempfile
# Create a request object with URL and headers
url = “http://fenixservices.fao.org/faostat/static/bulkdownloads/Production_Crops_Livestock_E_Oceania.zip”
header = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) '}
req = urllib.request.Request(url=url, headers=header)
# Define the destination file
dest_file = tempfile.gettempdir() + '/' + 'crop.zip'
print(f“File located at:{dest_file}”)
# Create an http response object
with urllib.request.urlopen(req) as response:
# Create a file object
with open(dest_file, "wb") as f:
# Copy the binary content of the response to the file
shutil.copyfileobj(response, f)
Based on https://stackoverflow.com/a/48691447/2641825 for the request part and https://stackoverflow.com/a/66591873/2641825 for the header part, see also urllib's documentation at https://docs.python.org/3/howto/urllib2.html

Requesting and Parsing a JSON with Python

I have this code below that I'm working on as part of an AI project. I'm looking to get tags that the user searches and return a url of a post with said tags.
from meya import Component
import requests
import json
API_URL = "https://e621.net/post/index.json?limit=1&tags=rating:s+order:random+{tag}"
class e621_call(Component):
"""Produces a e621 post based on the user's tags."""
def start(self):
tag = self.properties.get('tag') or \
self.db.flow.get('tag')
response = requests.get(API_URL.format(tag=tag))
img = response.json()['file_url']
message = self.create_message(text=img)
return self.respond(message=message, action="next")
Everything is fine up until I assign img to the file_url value, which brings up a
TypeError: list indices must be integers, not str
For the record, I am using meya.ai for this, and the packages are not the issue
Your API returns a dictionary inside a list. Get inside the list first then you can do what you wish with the dictionary.
response = requests.get(API_URL)
foo = json.loads(response.content)
file_url = foo[0].get('file_url')
If you plan on having multiple dictionaries returned inside the list, you can just loop through foo and find the multiple urls.
for d in foo:
print d.get('file_url')
Also, I prefer to not use .json() (As you may have noticed I didn't include it in my answer) because that way you can correctly check for the status_code first before proceeding. Otherwise if you get a 404 or a 500 for example, you will get errors.
if response.status_code == 200:
do stuff here
else:
print "Something is wrong"
I found a temporary workthrough, replacing response.json()['file_url'] with response.json()[0]['file_url'] works fine in the AI, although it still gives me the error.

How can I test "uploading a file" using Tornado unit tests?

I'm want to test my web service (built on Tornado) using tornado.testing.AsyncHTTPTestCase. It says here that using POST for AsyncHttpClients should look like the following.
from tornado.testing import AsyncHTTPTestCase
from urllib import urlencode
class ApplicationTestCase(AsyncHTTPTestCase):
def get_app(self):
return app.Application()
def test_file_uploading(self):
url = '/'
filepath = 'uploading_file.zip' # Binary file
data = ??????? # Read from "filepath" and put the generated something into "data"
self.http_client.fetch(self.get_url(url),
self.stop,
method="POST",
data=urlencode(data))
response = self.wait()
self.assertEqual(response.code, 302) # Do assertion
if __name__ == '__main__':
unittest.main()
The problem is that I've no idea what to write at ???????. Are there any utility functions built in Tornado, or is it better to use alternative libraries like Requests?
P.S.
... actually, I've tried using Requests, but my test stopped working because probably I didn't do good for asynchronous tasking
def test_file_uploading(self):
url = '/'
filepath = 'uploading_file.zip' # Binary file
files = {'file':open(filepath,'rb')}
r = requests.post(self.get_url(url),files=files) # Freezes here
self.assertEqual(response.code, 302) # Do assertion
You need to construct a multipart/form-data request body. This is officially defined in the HTML spec. Tornado does not currently have any helper functions for generating a multipart body. However, you can use the MultipartEncoder class from the requests_toolbelt package. Just use the to_string() method instead of passing the encoder object directly to fetch().

Categories

Resources