Flask / Mongodb WebApp Prueba inconsistente
-
13-12-2019 - |
Pregunta
Tengo una prueba de integración de matraz respaldada por un MongoDB de 1 nodo que falla al azar:
pytest/test_webapi.py:59: in test_register_test
> assert res.status_code == 302
E assert <Response streamed [404 NOT FOUND]>.status_code == 302
La tasa de falla es aproximadamente un 50%.
Prueba en test_webapi.py mirando así:
def test_register_user(self):
res = self.client.get("/logout")
class MySMTPServer(smtpd.SMTPServer):
mails = []
def process_message(self, peer, mailfrom, rcpttos, data):
self.mails.append((rcpttos[0], data))
server = MySMTPServer(('localhost', 12345), None)
t = threading.Thread(target=asyncore.loop, args=(1,))
t.start()
time.sleep(.1)
try:
res = self.client.post("/register", data=self.registration)
assert res.status_code == 200
mail, hash = server.mails[0]
self.conn.fsync()
time.sleep(.1)
res = self.client.get('/activate/' + hash)
assert res.status_code == 302
finally:
server.close()
Los métodos de matraz relevantes de webapi.py:
@app.route("/register", methods=["POST"])
def register_user():
mail = flask.request.form['mail']
user = flask.request.form["user"]
pw = flask.request.form["pass"]
hash = users.register(user, pw, mail=mail)
return flask.jsonify({'_id': None}) # XXX
@app.route('/activate/<hash>', methods=['GET'])
def activate_user(hash):
key = users.activate(hash=hash)
if not key:
flask.abort(404)
return flask.redirect("/")
... están respaldados por métodos de acción:
make_key = lambda : base64.encodestring(os.urandom(32)).strip()
def register(self, user, pw, **kw):
hash = self.make_key()
user = self.new(user, pw, activation=hash, **kw)
self._send_mail(**user)
return hash
def activate(self, hash):
user = self.users.find_one({'activation': hash})
if not user:
return None
key = self.make_key()
activation = {
'$unset': {'activation': 1},
'$set': {'status': 'active', 'key': key} }
self.users.update({'_id': user['_id']}, activation)
return user
... donde self.users es una colección mongodb.
Self.New () Persiste la entidad usando Safe= True.
Curiosamente, varias otras pruebas que realizan cosas similares nunca parecen encontrar este problema.
Había pensado que esto sería suficiente para asegurarse de que el objeto persistido fuera visible para otros hilos en el grupo de conexión Pymongo.¿Qué parte de la documentación de Mongodb / Pymongo debería haber leído más detenidamente?¿O hay alguna interacción extraña con Asyncore?
Solución
(portado del hilo de los comentarios)
En el contexto de las pruebas, ¿es el valor de data
solo la cadena codificada de base de la clave de activación?Base64 contiene letras y dígitos, pero también "+" y "/", ambos serán mal interpretados por los analizadores de URL (particularmente "/").