Use pytest parametrize inside test - pytest

Let's say I have the following pytest-django tests:
def test_get_color_by_id(client):
color = Color.objects.create(name="Green")
response = client.get(f"/api/colors/{color.pk}/")
assert response.status == 200
assert response.json() == {"id": color.pk, "name": color.name}
def test_get_color_by_name(client):
color = Color.objects.create(name="Green")
response = client.get(f"/api/color_names/{color.name}/")
assert response.status == 200
assert response.json() == {"id": color.pk, "name": color.name}
There's a lot of duplication here. Would be great to use pytest's parametrize feature like below but it's not working:
def test_get_color(client):
color = Color.objects.create(name="Green")
with pytest.mark.parametrize("endpoint", [
f"/api/colors/{color.pk}/",
f"/api/color_names/{color.name}/",
]):
response = client.get(f"/api/color_names/{color.name}/")
assert response.status == 200
assert response.json() == {"id": color.pk, "name": color.name}
Is this even possible or does pytest not support it?

See this page for a description of how to write parametrized tests. The parameters are given by decorating the test function, not by entering a with block:
#pytest.mark.parametrize("endpoint", [
f"/api/colors/{color.pk}/",
f"/api/color_names/{color.name}/",
])
def test_get_color(client, endpoint):
color = Color.objects.create(name="Green")
response = client.get(endpoint)
assert response.status == 200
assert response.json() == {"id": color.pk, "name": color.name}
Edit: I didn't read the question carefully enough, and didn't notice that the endpoint parameters were f-strings. You can get this specific example to work by parametrizing the test function with either regular strings or lambda functions:
Regular strings:
#pytest.mark.parametrize("endpoint", [
"/api/colors/{color.pk}/",
"/api/color_names/{color.name}/",
])
def test_get_color(client, endpoint):
color = Color.objects.create(name="Green")
endpoint = endpoint.format(color=color)
response = client.get(endpoint)
assert response.status == 200
assert response.json() == {"id": color.pk, "name": color.name}
Lambda functions:
#pytest.mark.parametrize("endpoint", [
lambda color: f"/api/colors/{color.pk}/",
lambda color: f"/api/color_names/{color.name}/",
])
def test_get_color(client, endpoint):
color = Color.objects.create(name="Green")
response = client.get(endpoint(color))
assert response.status == 200
assert response.json() == {"id": color.pk, "name": color.name}
You may also be interested in the pytest-subtests plugin, although in my experience it's painful to use, because it causes pytest's "only rerun failed tests" options to not work like you'd expect.

Related

facebook messenger curl request returns <Response [400]>

I am new to the messenger API, I want to send a message using a curl post request, this is my code:
import requests
ACCESS_TOKEN = an Active access token
fb_url = "https://graph.facebook.com/v10.0/me/messages"
data = {
'recipient': '{"id":4098757906843152}',
"message": {
"text": "hello, world!"
},
"messaging_type": "MESSAGE_TAG",
"tag": "ACCOUNT_UPDATE"
}
params = {'access_token': ACCESS_TOKEN}
resp = requests.post(fb_url, params=params, data=data)
print(resp)
unfortunately, I got this message <Response [400]>
any help would be appreciated
You need to change data to json.
See https://stackoverflow.com/a/26344315/603756
Starting with Requests version 2.4.2, you can use the json= parameter (which takes a dictionary) instead of data= (which takes a string) in the call
import requests
ACCESS_TOKEN = '<access_token>'
fb_url = 'https://graph.facebook.com/v10.0/me/messages'
data = {
'recipient': '{"id":<psid>}',
"message": {
"text": "hello, world!"
}
}
params = {'access_token': ACCESS_TOKEN}
resp = requests.post(fb_url, json=data, params=params)
print(resp)

Akka HTTP, Spray Json and Option Fields Failing as Required

I have a case class:
case class OpcTagPlaybook(name: String, tags: Seq[OpcTagAtTime], looped: Boolean, enabled: Option[String])
With an optional enabled field that will contain a date.
Spray Json describes encoding/decoding:
implicit val opcTagPlaybookFormat = jsonFormat4(OpcTagPlaybook)
And a route in akka http:
post {
entity(as[OpcTagPlaybook]) { playbook =>
val playbookCreated: Future[_] =
(opcTagPlaybookActor ? UpsertPlaybook(playbook))
onSuccess(playbookCreated) { _ =>
log.info("Created playbook [{}]", playbook.name)
complete((StatusCodes.Created, "ok"))
}
}
})
For some reason posting without the createdAt field fails:
Posting:
{"name": "test1",
"tags":[{"offset": 100, "tag": "hello", "value": "yo"}],
"looped": true
}
Fails:
The request content was malformed:
Object is missing required member 'enabled'
And if I post created it gives me another error:
{"name": "test1",
"tags":[{"offset": 100, "tag": "hello", "value": "yo"}],
"looped": true,
"enabled": "2018-08-08"
}
gives
The request content was malformed:
spray.json.JsString cannot be cast to scala.Option
I'm assuming this is some interplay between akka http and so I'm going to just deal with the input more manually but I'd just like to understand what I'm doing wrong here.

Status code from Graph API after successful communication

my Facebook messenger based Echo-bot gives a wrong status code. Though the end user(admin until now) receives the accurate echoed message, the feedback my webhook receives gives from Graph API is:
{"error":{"message":"(#100) No matching user found","type":"OAuthException","code":100,"error_subcode":2018001,"fbtrace_id":"Fan1swU4dF8"}}
Even after much reviewing and surfing, I haven't been able to find out the problem with my webhook code.Below it is:
import os, sys
import requests
from flask import Flask, request
import json
from random import random, choice
page_access_token="page_access_code"
chatbot=Flask(__name__)
#chatbot.route('/', methods=['GET'])
def verify():
print("Handling verification...")
if request.args.get('hub.verify_token', '')=='verify_token':
print("Verified!!")
return request.args.get("hub.challenge",'')
else:
print("Wrong request!!")
return "error!!"
#chatbot.route('/', methods=['POST'])
def webhook():
data=request.get_json()
log(data)
if data["object"]=="page":
for entry in data["entry"]:
for things in entry["messaging"]:
if things.get("message"):
s_id= things["sender"]["id"]
r_id= things["recipient"]["id"]
log("Sender id:"+ s_id)
log("Receiver id: "+ r_id)
try:
messaging_text= things["message"]["text"]
send_message(s_id, str(messaging_text))
except:
send_message(s_id, "Sorry!! Couldn't understand that..")
if things.get("delivery"):
log("message delivered..")
elif things.get("optin"):
pass
elif things.get("postback"):
pass
return 'ok', 200
def send_message(r_id, messaging_text):
r_id=str(r_id)
log("sending message to {recipient}: {text}".format(recipient=r_id, text=messaging_text))
params = {
"access_token": page_access_token
}
headers = {
"Content-Type": "application/json"
}
data = json.dumps({
"recipient": {
"id": r_id
},
"message": {
"text": str(messaging_text)
}
})
r = requests.post("https://graph.facebook.com/v2.12/me/messages", params=params, headers=headers, data=data)
if r.status_code != 200:
log(r.status_code)
log(r.text)
def log(message):
print(message)
sys.stdout.flush()
if __name__=="__main__":
chatbot.run(debug=True, port=5000)
PS. I am a noob so a proper description or a link will be really helpful for me to know the flaw.

How to validate response in Postman?

I am trying to validate response body including errors in postman. How can I validate the response and text below?
{
"responseHeader": {
"publisherId": "12345",
"responseId": "abbcb15d79d54f5dbc473e502e2242c4abbcb15d79d54f5dbc473e502e224264",
"errors": [
{
"errorCode": "1004",
"errorMessage": "XXXX Not Found"
}
]
}
}
These are my tests which are failing:
tests['response json contains responseHeader'] = _.has(responseJSON, 'responseHeader');
tests['response json contains errors'] = _.has(responseJSON, 'responseHeader.publisherId');
tests["Response has publisher id"] = responseJSON.publisherId === 10003;
In the "Test" tab, parse your response body into an object, then use JavaScript to perform your tests.
var data = JSON.parse(responseBody);
tests["publisherId is 12345"] = data.responseHeader.publisherId === "12345";
Take a look at the test examples at the Postman site:
https://www.getpostman.com/docs/postman/scripts/test_scripts
https://www.getpostman.com/docs/postman/scripts/test_examples

Yahoo Gemini API Python Example to fetch reports?

https://developer.yahoo.com/gemini/
I need to download yahoo gemini ad reports. But yahoo documentation only has php code and no python. can someone please share any inputs ?
I have done oauth before but it had some basic documentation
Try this lib https://github.com/josuebrunel/yahoo-oauth with examples below
import urllib
import json
import time
from yahoo_oauth import OAuth2
oauth = OAuth2(None, None, from_file='credentials.json')
if not oauth.token_is_valid():
oauth.refresh_access_token()
# get all accounts
response = oauth.session.get("https://api.admanager.yahoo.com/v1/rest/advertiser/")
data = response.content
print data
jdata = json.loads(data)
for j in jdata['response']:
print "{} {}".format(j['id'], j['advertiserName'])
# get advertiser data
advertiser_id = 12345678
report_date_from = "2016-08-28"
report_date_to = "2016-08-28"
payload = {"cube": "performance_stats",
"fields": [
{"field": "Day"},
{"field": "Impressions"},
{"field": "Conversions"},
{"field": "Spend"},
{"field": "Campaign ID"}
],
"filters": [
{"field": "Advertiser ID", "operator": "=", "value": advertiser_id},
{"field": "Day", "operator": "between", "from": report_date_from, "to": report_date_to}
]}
response = oauth.session.post("https://api.admanager.yahoo.com/v1/rest/reports/custom?reportFormat=json", json=payload)
print response.content
jdata = json.loads(response.content)
job_id = jdata['response']['jobId']
# you will need to add some loop and waits before the report is ready
time.sleep(60)
url = "https://api.admanager.yahoo.com/v1/rest/reports/custom/{}?advertiserId={}".format(job_id, advertiser_id)
response = oauth.session.get(url)
print response.content
# report will be returned as url
rdata = json.loads(response.content)
if 'status' in rdata['response'] and rdata['response']['status'] == 'completed':
report = urllib.urlopen(rdata['response']['jobResponse']).read()
print report