pytest monkeypatch fails second time is called - google-app-engine

Hi I'm trying ot use pytest to test some methods from an appengine app. Both methods use google.appengine.api.users.get_current_user to access current logged in user:
#pytest.fixture
def api_client():
tb = testbed.Testbed()
tb.activate()
tb.init_datastore_v3_stub()
tb.init_memcache_stub()
tb.init_user_stub()
ndb.get_context().clear_cache()
api.api_app.testing = True
yield api.api_app.test_client()
tb.deactivate()
def test_get_pipelines(api_client, mocked_google_user):
pips = _insert_pipelines()
user = LUser(user_id=mocked_google_user.user_id(), pipelines=[p.key for p in pips])
user.put()
r = api_client.get('/api/v1/pipelines')
assert r.status_code == 200
expected_result = {
'own': [
pips[0].to_dic(),
pips[1].to_dic(),
]
}
assert json.loads(r.data) == expected_result
def test_get_pipelines_no_pipelines(api_client, mocked_google_user):
r = api_client.get('/api/v1/pipelines')
assert r.status_code == 200
expected_result = {
'own': []
}
assert json.loads(r.data) == expected_result
I've created a pytest fixture to provide it:
#pytest.fixture(autouse=True)
def mocked_google_user(monkeypatch):
google_user = MockGoogleUser()
monkeypatch.setattr('google.appengine.api.users.get_current_user', lambda: google_user)
return google_user
It works fine for the first test but when executing ght second i thows an error like:
obj = <module 'google' from 'C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\google\__init__.pyc'>
name = 'appengine', ann = 'google.appengine'
def annotated_getattr(obj, name, ann):
try:
obj = getattr(obj, name)
except AttributeError:
raise AttributeError(
'%r object at %s has no attribute %r' % (
> type(obj).__name__, ann, name
)
)
E AttributeError: 'module' object at google.appengine has no attribute 'appengine'
winvevn\lib\site-packages\_pytest\monkeypatch.py:75: AttributeError
I can't find why. Any suggestions?

I've managed to solve this by importing users locally on the test file
from google.appengine.api import users
and then monkeypatch this way:
#pytest.fixture(autouse=True)
def mocked_google_user(monkeypatch):
google_user = MockGoogleUser('test#example.com', 'test user', '193934')
monkeypatch.setattr(users, 'get_current_user', lambda: google_user)
return google_user

Related

TypeError: object of type 'Cell' has no len()

I'm trying to
I'm trying to run a login test in through the pytest taht should take an emails and passwords from an excel file and when i'm runing it I got TypeError: object of type 'Cell' has no len().
Problem is that this Type Error is not in my code it's in utils file of PyCharm.
Is anyone know how to deal with that type of errors?
PyCharm utils.py file address:
venv\lib\site-packages\selenium\webdriver\common\utils.py:148: TypeError:
value = (<Cell 'Sheet1'.A2>,)
def keys_to_typing(value: Iterable[AnyKey]) -> List[str]:
"""Processes the values that will be typed in the element."""
_typing: List[str] = []
for val in value:
if isinstance(val, Keys):
# Todo: Does this even work?
_typing.append(val)
elif isinstance(val, (int, float)):
val = str(val)
for i in range(len(val)):
_typing.append(val[i])
else:
for i in range(len(val)):
E TypeError: object of type 'Cell' has no len()
This is my code:
import time
import pytest
from selenium import webdriver
from PageObjects.Login_page import Login
from Utilities.readProperties import ReadConfig
from Utilities.custom_logger import LogGen
from TestCases.contest import setup
from Utilities import XLUtils
class TestLogin002DDT:
appUrl = "https://admin-demo.nopcommerce.com/"
path = ".//TestData/document.xlsx"
logger = LogGen.log_gen()
def test_login_002_data_driven_test(self, setup):
self.logger.info("******************** Test_002_DDT_login **********************")
self.logger.info("******************** DDT login verification **********************")
self.driver = setup
self.driver.get(self.appUrl)
self.lp = Login(self.driver)
self.rows = XLUtils.get_row_count(self.path, "Sheet1")
print("Number of rows: ", self.rows)
list_status = []
for row in range(2, self.rows+1):
self.user = XLUtils.read_data(self.path, "Sheet1", row, 1)
self.password = XLUtils.read_data(self.path, "Sheet1", row, 2)
self.expected_result = XLUtils.read_data(self.path, "Sheet1", row, 3)
self.lp.set_user_name(self.user)
self.lp.set_password(self.password)
self.lp.click_login()
time.sleep(3)
actual_title = self.driver.title
expected_title = "Dashboard / nopCommerce administration"
if actual_title == expected_title:
if self.expected_result == 'Pass':
self.logger.info("******************** Login verification PASSED **********************")
self.lp.click_logout()
list_status.append("Pass")
elif self.expected_result == "Fail":
self.logger.info("******************** Login verification FAILED **********************")
self.lp.click_logout()
list_status.append("Fail")
elif actual_title != expected_title:
if self.expected_result == 'Pass':
self.logger.info("******************** Login verification FAILED **********************")
self.lp.click_logout()
list_status.append("Fail")
elif self.expected_result == "Fail":
self.logger.info("******************** Login verification PASSED **********************")
self.lp.click_logout()
list_status.append("Pass")
if "Fail" not in list_status:
self.logger.info("################# Login Data Driven Test PASSED ################")
self.driver.close()
assert True
else:
self.logger.info("################# Login Data Driven Test FAILED ################")
self.driver.close()
assert False
self.logger.info("******** End of DDT Login Test *********")
self.logger.info("******** TestLogin002DDT Completed *********")

How to parse array values from Json in Jmeter

For the below response I need to fetch the rideId and pass it to the next request in Jmeter.Also ,the API that generates below response should be executed until the eventType is HANDSHAKE.
[{"id":90856,"eventType":"HANDSHAKE","parameters":"{\"handshakeExpiration\":1669217518986,\"rideId\":3107}"}]
I am using the code :
import groovy.json.JsonSlurper;
def jsonSlurper=new JsonSlurper();
def apiDetailsArr=jsonSlurper.parse(prev.getResponseData())
def apiDetails=apiDetailsArr.size()>0?apiDetailsArr.get(0):null
def shouldRun = "1"
if(apiDetails!=null)
{
log.info("details",apiDetails.eventType+"")
if(apiDetails.eventType="HANDSHAKE"){
shouldRun="0"
}
def object=jsonSlurper.parseText(apiDetails.parameters)
log.info("xyz",object+"")
def id=object.rideId;
log.info("id",id+"")
vars.put("id", id+"")
}
else{
shouldRun="1"`enter code here`
}
`Condition for while controller : `${__javaScript( "${shouldRun}" != "0",)}``
All your log.info function calls cause syntax errors, you can see it yourself in (surprise!) the jmeter.log file
I fail to see where you're assigning shouldRun JMeter Variable which is used in the While Controller
Suggested code change:
import groovy.json.JsonSlurper;
def jsonSlurper = new JsonSlurper();
def apiDetailsArr = jsonSlurper.parse(prev.getResponseData())
def apiDetails = apiDetailsArr.size() > 0 ? apiDetailsArr.get(0) : null
def shouldRun = "1"
if (apiDetails != null) {
log.info("details", apiDetails.eventType + "")
if (apiDetails.eventType = "HANDSHAKE") {
shouldRun = "0"
}
def object = jsonSlurper.parseText(apiDetails.parameters)
log.info("xyz" + object)
def id = object.rideId;
log.info("id" + id)
vars.put("id", id as String)
} else {
shouldRun = "1"
}
vars.put("shouldRun", shouldRun)
More information on Groovy scripting in JMeter: Apache Groovy: What Is Groovy Used For?

Mocking urllib.request.urlopen using unittest

I'm trying to mock this urlopen function. Got a couple of solutions from other similar questions but none of them seems to work.
def lambda_handler(event, context):
try:
request = urllib.request.Request(url = URL, data = data, method = method, headers = headers)
with urllib.request.urlopen(request) as httpResponse:
# print(httpResponse.read().decode('utf-8'))
string = httpResponse.read().decode('utf-8')
response = json.loads(string)
print(response)
return response
Approach tried:
class mock_request():
class Request():
....
def urlopen(*args, **krwargs):
return {}
#mock.patch(.....urllib.request, mock_request)
I think the easiest way is to patch __enter__ + __exit__ methods. Just an example:
def lambda_handler(event, context):
try:
# some request... just an example
request = Request('https://restcountries.com/v3.1/name/belarus')
with urllib.request.urlopen(request) as resp:
string = resp.read().decode('utf-8')
return json.loads(string)
except Exception:
pass
Test:
from unittest import TestCase, mock
from unittest.mock import Mock
class TestExample(TestCase):
def test_lambda_handler(self):
print(lambda_handler(1, 2)) # real result from restcountries
open_mock = Mock(
# resp.read().decode('utf-8') will return static value '[]'
__enter__=Mock(return_value=Mock(read=Mock(return_value=Mock(decode=Mock(return_value='[]'))))),
__exit__=Mock(),
)
with mock.patch('urllib.request.urlopen', return_value=open_mock):
print(lambda_handler(1, 2)) # []
# resp.read().decode('utf-8') will return dynamic values
open_mock = Mock(
__enter__=Mock(
return_value=Mock(
read=Mock(return_value=Mock(decode=Mock(side_effect=[
'[{"name": "N S"}]',
'[{"name": "D G"}]']
)))
)
),
__exit__=Mock(),
)
with mock.patch('urllib.request.urlopen', return_value=open_mock):
print(lambda_handler(1, 2)) # [{"name": "N S"}]
print(lambda_handler(1, 2)) # [{"name": "D G"}]

Adding methods to GAE database class

I am messing around with GAE. I want to place my database object in one file and call it from another. Here is the DB object:
import webapp2
import os
import jinja2
import json
import logging
import main
from google.appengine.ext import db
class User(db.Model):
user_name = db.StringProperty(required = True)
hashed_password = db.StringProperty(required = True)
email = db.EmailProperty(required = True)
created_dttm = db.DateTimeProperty(auto_now_add = True)
last_modified = db.DateTimeProperty(auto_now = True)
coords = db.GeoPtProperty(required = False)
# def as_dict(self):
# time_fmt = '%c'
# d = {
# 'subject':self.subject,
# 'content':self.content,
# 'created':self.created_dttm.strftime(time_fmt),
# 'last_modified': self.last_modified.strftime(time_fmt)
# }
# return d
def isValueUnique(self,column,value):
result = None
q = User.all()
q.filter(column, value)
result = q.get()
return result
I cannot instantiate the DB because it thinks I'm trying to store data.
I want to call the isValueUnique method from another file like so:
import webapp2
import os
import jinja2
import json
import logging
import main
import database
import validation
from google.appengine.ext import db
class SignUp(main.Handler):
def post(self):
user_username = self.request.get("username")
user_email = self.request.get("email")
user_pass = self.request.get("password")
user_verify = self.request.get("verify")
valid = validation.Valid()
error1=""
error2=""
error3=""
error4=""
q = database.User.all()
q.filter("username =", user_username)
result = q.get()
if result:
error1="Username already taken"
if (not valid.valid_user(user_username)) and (not error1):
error1 = "Enter a valid username"
if not valid.valid_password(user_pass):
error2 = "Enter a valid password"
if not valid.valid_pass_match(user_pass,user_verify):
error3 = "Passwords must match"
# Email Validation
email=valid.valid_email(user_email)
if not email:
error4 = "Invalid email"
email=""
elif not database.User.isValueUnique("email",email):
error4 = "Email already in use, please sign in"
email=""
I get this error:
elif not database.User.isValueUnique("email",email):
TypeError: unbound method isValueUnique() must be called with User instance as first argument (got str instance instead)
I can't instantiate User like I already said. What is the work around here?
database.User.isValueUnique("email",email)
This is attempting to call a method on the database.User class, but isValueUnique is an instance method.
If you decorate isValueUnique with #staticmethod you'll get farther.
Where are you trying to instantiate a User?

how to handle javascript callback return data in python

var req = new XMLHttpRequest();
req.open('GET', '/Search?' + query, async);
if (async) {
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
var response = null;
try {
response = JSON.parse(req.responseText);
} catch (e) {
response = req.responseText;
}
callback(response);
This callback function returns values to my python code (I am using GAE with python 2.7).
class KeywordSearchRPCHandler(webapp2.RequestHandler):
def __init__(self):
webapp2.RequestHandler.__init__(self)
self.methods = RPCMethods()
def get(self):
func = None
action = self.request.get('action')
if action:
if action[0] == '_':
self.error(403) # access denied
return
else:
func = getattr(self.methods, action, None)
if not func:
self.error(404) # file not found
return
else :
args = ()
while True:
key = 'arg%d' % len(args)
val = self.request.get(key)
#print val
if val:
args = (json.loads(val))
else:
break
result = func(*args)
self.response.out.write(json.dumps(result))
This is the code that handles the callback function.
I get the error init() takes exactly 1 argument (3 given)
Could you please help me modify my code. Thanks a lot in advance.
Here is the documentation: Docs
webapp2.RequestHandler.__init__(request=None, response=None) is the signature.
So add request and response as parameters to your init and you should be fine.
Change def __init__ (self) to def __init__(self, request=None, response=None). This will fix the bug.
And you probably want to call super properly instead of calling __init__ on the class here: webapp2.RequestHandler.__init__(self)
This should most likely be super(KeywordSearchRPCHandler, self).__init__(request, response) instead.
The init handler:
class RPCHandler(webapp2.RequestHandler):
""" Allows the functions defined in the RPCMethods class to be RPCed."""
def __init__(self, request, response):
super(RPCHandler, self).__init__(request, response)
self.methods = RPCMethods()
But I do not understand your json.loads(val) in your GET, because you send a query string and not a json request.
Below is an example post, handling a json post:
def post(self):
data = self.request.body
args = loads(data)
if 'action' not in args:
self.error(405) # access denied
return
func = args['action']
if func[0] == '_':
self.error(403) # access denied
return
func = getattr(self.methods, func, None)
if not func:
self.error(404) # file not found
return
# action handler aanroepen
result = func(args)
self.response.out.write(json.dumps(result))
If you use a GET with a query string webapp2 will handle the request. From the docs:
# An iterable with all items in the MultiDict:
# [('check', 'a'), ('check', 'b'), ('name', 'Bob')]
self.request.GET.items()

Resources