Testing Flask applications is done with:
# main.py
from flask import Flask, request
app = flask.Flask(__name__)
#app.route('/')
def index():
s = 'Hello world!', 'AJAX Request: {0}'.format(request.is_xhr)
print s
return s
if __name__ == '__main__':
app.run()
Then here is my test script:
# test_script.py
import main
import unittest
class Case(unittest.TestCase):
def test_index():
tester = app.test_client()
rv = tester.get('/')
assert 'Hello world!' in rv.data
if __name__ == '__main__':
unittest.main()
In the test output, I'll get:
Hello world! AJAX Request: False
Question
How do I test my app with AJAX requests?
Try this:-
def test_index():
tester = app.test_client()
response = tester.get('/', headers=[('X-Requested-With', 'XMLHttpRequest')])
assert 'Hello world!' in response.data
import json
def test_index():
data = json.dumps({})
client = app.test_client()
headers = {
'Content-Type': 'application/json',
}
response = client.post('/', data=data, headers=headers)
data = json.loads(response.data)
assert data
`
Related
I'm trying to verify that the Webhook received is coming from Shopify. They have this doc, but it doesn't work (getting type errors).
Here's what I have so far. It produces no errors, but the verify_webhook function always returns false.
from flask import Flask, request, abort
import hmac
import hashlib
import base64
app = Flask(__name__)
SECRET = '...'
def verify_webhook(data, hmac_header):
digest = hmac.new(SECRET.encode('utf-8'), data, hashlib.sha256).digest()
genHmac = base64.b64encode(digest)
return hmac.compare_digest(genHmac, hmac_header.encode('utf-8'))
#app.route('/', methods=['POST'])
def hello_world(request):
print('Received Webhook...')
data = request.get_data()
hmac_header = request.headers.get('X-Shopify-Hmac-SHA256')
verified = verify_webhook(data, hmac_header)
if not verified:
return 'Integrity of request compromised...', 401
print('Verified request...')
if __name__ == '__main__':
app.run()
What am I doing wrong?
Answer:
from flask import Flask, request, abort
import hmac
import hashlib
import base64
app = Flask(__name__)
SECRET = '...'
def verify_webhook(data, hmac_header):
digest = hmac.new(SECRET.encode('utf-8'), data, hashlib.sha256).digest()
genHmac = base64.b64encode(digest)
return hmac.compare_digest(genHmac, hmac_header.encode('utf-8'))
#app.route('/', methods=['POST'])
def hello_world(request):
print('Received Webhook...')
data = request.data # NOT request.get_data() !!!!!
hmac_header = request.headers.get('X-Shopify-Hmac-SHA256')
verified = verify_webhook(data, hmac_header)
if not verified:
return 'Integrity of request compromised...', 401
print('Verified request...')
if __name__ == '__main__':
app.run()
Issue was in the data = request.get_data() line.
I have a flask app that works (tested with postman).
I am now writing unittest for it as I am trying with Travis and CI on my repository, I use nose2.
The test class I wrote is this:
import unittest
import requests
from myapp import app
class ProjectTests(unittest.TestCase):
############################
#### setup and teardown ####
############################
# executed prior to each test
def setUp(self):
app.config["TESTING"] = True
app.config["DEBUG"] = False
self.app = app.test_client()
self.assertEquals(app.debug, False)
# executed after each test
def tearDown(self):
pass
########################
#### helper methods ####
########################
###############
#### tests ####
###############
def test_main_page(self):
response = self.app.get("/", follow_redirects=True)
# self.assertIn(b"Hello World!", response.data)
# response = app.test_client().get('/')
assert response.status_code == 200
# print(response.data)
assert response.data == b"Hello, world!"
def test_register(self):
# import requests
url = "http://127.0.0.1:5000/register"
payload = '{\n\t"username": "bruno",\n\t"password": "asdf"\n}\n'
headers = {"Content-Type": "application/json"}
response = requests.request("POST", url, headers=headers, data=payload)
# print(response.text.encode("utf8"))
print(response.json()["message"])
assert response.status_code == 400 # user already exists
if __name__ == "__main__":
unittest.main()
If I run the app and then I copy and paste the test_register method, i.e.
import requests
url = "http://127.0.0.1:5000/register"
payload = '{\n\t"username": "bruno",\n\t"password": "asdf"\n}\n'
headers = {"Content-Type": "application/json"}
response = requests.request("POST", url, headers=headers, data=payload)
# print(response.text.encode("utf8"))
print(response.json()["message"])
everything is fine. It fails if I run nose2 and I get a connection refused error.
If I comment the test_register method and nose2 runs fine. I reckon I am implementing the two tests differently.
Any help on how to fix this?
i'm trying to make an app in flask-python that using a json post send an audio using the gtts google library as the answer, but my method doesn't work. My code is the following.
from gtts import gTTS
from flask import Flask, send_file, request
app = Flask(__name__)
#app.route("/")
def t2s():
text = request.get_json()
obj = gTTS(text = text, slow = False, lang = 'en')
obj.save('audio.wav')
return send_file('audio.wav')
if __name__ == "__main__":
app.run(port=3000 , debug=True, use_reloader=True, host='0.0.0.0')
any suggestions?, i'm using postman.
Thanks a lot for the possible help
Flask as default doesn't get POST requests and you have to use methods=['POST', 'GET']
from gtts import gTTS
from flask import Flask, send_file, request
app = Flask(__name__)
#app.route("/", methods=['POST', 'GET'])
def t2s():
text = request.get_json()
print(text)
obj = gTTS(text = text, slow = False, lang = 'en')
obj.save('audio.wav')
return send_file('audio.wav')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=3000)
And test (using mplayer on Linux):
import requests
import os
data = 'Hello World'
r = requests.post('http://127.0.0.1:3000/', json=data)
open('output.wav', 'wb').write(r.content)
os.system('mplayer output.wav')
I have the following flask api, which just returns echo of its input:
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class query(Resource):
def get(self, a_string):
return{
'original': a_string,
'echo': a_string
}
api.add_resource(query,'/echo/<a_string>')
if __name__ == '__main__':
app.run()
Then, when I try to use python requests to make queries to my api:
import json
def query(text):
payload = {'echo': str(text)}
headers = {'content-type': 'application/x-www-form-urlencoded'}
r = requests.request("POST", 'http://127.0.0.1:5000', data=payload, headers=headers)
print(r)
#data = json.loads(r.text)
#return data
query('hi')
I keep getting:
<Response [404]>
Any idea of how to fix this issue? Interestingly when I go to my browser and do:
http://127.0.0.1:5000/echo/hi
I get:
{"original": "hi", "echo": "hi"}
But sending a POST to / with a payload of {"echo": whatever} is not at all the same as sending a GET to /echo/whatever. Your API expects the latter.
def query(text):
r = requests.get("http://127.0.0.1:5000/echo/{}".format(text))
Or, change your API so it does expect that:
class query(Resource):
def post(self):
a_string = request.form["echo"]
return {
'original': a_string,
'echo': a_string
}
api.add_resource(query, '/')
import bottle
from bottle import route, run
#route('/', method='GET')
def homepage():
return {'foo' : 'bar'}
if __name__=='__main__':
bottle.debug(True)
run(host='0.0.0.0', port= 8080, reloader = True)
This config will return a json object representing the dict from homepage with HTTP status code 200. What should I do to return the same content but with, say, 202 status code?
You can set the response.status attribute:
from bottle import response
#route('/', method='GET')
def homepage():
response.status = 202
return {'foo' : 'bar'}