Frage

Ich habe einen Flask-Integrationstest, der von einem 1-Knoten-Mongodb unterstützt wird, der zufällig fehlschlägt:

pytest/test_webapi.py:59: in test_register_test
>           assert res.status_code == 302
E           assert <Response streamed [404 NOT FOUND]>.status_code == 302

Die Ausfallquote liegt bei etwa 50 %.

Testen Sie test_webapi.py folgendermaßen:

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()

Die relevanten Flask-Methoden von 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("/")

...werden durch Aktionsmethoden unterstützt:

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

...Dabei ist self.users eine Mongodb-Sammlung.

self.new() behält die Entität mit „safe=True“ bei.

Interessanterweise scheint dieses Problem bei mehreren anderen Tests, die ähnliche Dinge durchführen, nie aufzutreten.

Ich hatte gedacht, dass dies ausreichen würde, um sicherzustellen, dass das persistente Objekt für andere Threads im Pymongo-Verbindungspool sichtbar wäre.Welchen Teil der Mongodb/Pymongo-Dokumentation hätte ich sorgfältiger lesen sollen?Oder gibt es eine seltsame Interaktion mit Asyncore?

War es hilfreich?

Lösung

(portiert aus dem Kommentarthread)

Im Rahmen der Tests ist das data Wert nur die Base64-codierte Zeichenfolge des Aktivierungsschlüssels?base64 enthält Buchstaben und Ziffern, aber auch „+“ und „/“, die beide von URL-Parsern falsch interpretiert werden (insbesondere „/“).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top