2017-07-23 42 views
6

當我運行包括使用setuptools和nose2調用@classmethod的測試時,測試套件沒有完成,只是繼續運行。但是我已經檢查過測試確實通過並且達到了函數的結尾,測試套件並沒有完成運行。如果我使用decode_auth_token刪除測試,它工作正常。我能夠縮小它對班級方法所做的工作,因爲我也測試了其他班級方法,並且它們導致相同的問題當調用類方法時,Python Nose2測試未完成

有沒有人知道爲什麼會發生這種情況?下面是代碼中的相關片段,而不會在叫

@classmethod 
    def is_username_taken(cls, username): 
    return db.session.query(db.exists().where(User.username==username)).scalar() 

    @classmethod 
    def is_email_taken(cls, email): 
    return db.session.query(db.exists().where(User.email==email)).scalar() 

這個功能確實張貼了過多的代碼

代碼在我的用戶模型

@classmethod 
    def decode_auth_token(cls, auth_token): 
    try: 
     payload = jwt.decode(auth_token, config.SECRET_KEY, algorithms=['HS256']) 
     # check the hash of what we expect the token to be and token we got to be the same 
     if bcrypt.check_password_hash(User.by_id(payload['sub']).api_token_hash, auth_token): 
     return payload['sub'] 
     else: 
     return 'Token does not match Api Token.' 
    except jwt.ExpiredSignatureError: 
     return 'Signature expired. Please log in again.' 
    except jwt.InvalidTokenError: 
     return 'Invalid Token. Please log in again.' 

以下兩個功能也導致問題當調用時不會導致問題

@classmethod 
def by_username(cls, username): 
    return User.query.filter(User.username == username).first() 

這裏是測試

import unittest 
import sys 

from . import AppTestCase, API_ROOT 
from app.extensions import db, bcrypt 
from app.models import User, UserSchema, Location, Company 


class TestUserModel(AppTestCase): 
    def test_encode_auth_token(self): 
    user = User.by_username('jdoe') 
    auth_token = user.encode_auth_token(user.id) 
    self.assertTrue(isinstance(auth_token, bytes)) 

    def test_decode_auth_token(self): 
    user = User.by_username('jdoe') 
    auth_token = user.encode_auth_token(user.id) 
    self.assertTrue(isinstance(auth_token, bytes)) 
    self.assertEqual(User.decode_auth_token(auth_token), user.id) 
    print('DONE') 

第一個測試工作正常,第二次測試打印出Done並正確解碼的auth_token返回正確的用戶ID,但不會導致測試套件來完成。打印完成後它會繼續運行。

這裏是安裝腳本,我在運行了,並沒有阻止

running test 
Searching for nose2 
Best match: nose2 0.6.5 
Processing nose2-0.6.5-py3.6.egg 

Using XXX/.eggs/nose2-0.6.5-py3.6.egg 
running egg_info 
writing doomfist.egg-info/PKG-INFO 
writing dependency_links to XXX.egg-info/dependency_links.txt 
writing requirements to XXX.egg-info/requires.txt 
writing top-level names to XXX.egg-info/top_level.txt 
reading manifest file 'XXX.egg-info/SOURCES.txt' 
writing manifest file 'XXX.egg-info/SOURCES.txt' 
running build_ext 
/Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/python_dateutil-2.6.0-py3.6.egg/dateutil/parser.py:50: DeprecationWarning: invalid escape sequence \. 
/Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/python_dateutil-2.6.0-py3.6.egg/dateutil/parser.py:50: DeprecationWarning: invalid escape sequence \. 
/Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/python_dateutil-2.6.0-py3.6.egg/dateutil/tz/win.py:197: DeprecationWarning: invalid escape sequence \{ 
/Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/python_dateutil-2.6.0-py3.6.egg/dateutil/tz/win.py:247: DeprecationWarning: invalid escape sequence \{ 
/Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/python_dateutil-2.6.0-py3.6.egg/dateutil/tz/win.py:197: DeprecationWarning: invalid escape sequence \{ 
/Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/python_dateutil-2.6.0-py3.6.egg/dateutil/tz/win.py:247: DeprecationWarning: invalid escape sequence \{ 
NOT running in debug mode 
DONE 
^]^\[1] 35752 quit  python setup.py test 

編輯在使用python setup.py test

import os 
from setuptools import setup, find_packages, Command 

# Thanks http://stackoverflow.com/questions/3779915/why-does-python-setup-py-sdist-create-unwanted-project-egg-info-in-project-r 
class CleanCommand(Command): 
    """Custom clean command to tidy up the project root.""" 
    user_options = [] 
    def initialize_options(self): 
    pass 
    def finalize_options(self): 
    pass 
    def run(self): 
    os.system('rm -vrf ./build ./dist ./*.pyc ./*.tgz ./*.egg-info') 

with open('requirements.txt') as f: 
    requirements = f.read().splitlines() 

setup(
    name="XXX", 
    description="XXX", 
    version=1.0, 
    packages=find_packages(), 
    install_requires=requirements, 
    include_package_data=True, 
    test_suite='nose2.collector.collector', 
    tests_require=['nose2'], 
    cmdclass={ 
     'clean': CleanCommand, 
    } 
) 

輸出測試-----對不起,巨大的柱狀現在 在評論中有人的建議我使用調試器來確定它確實完成了測試。在tearDown()期間它實際上被卡住的地方。我的以下功能就是卡住的地方。

def tearDown(self): 
    """Clean db session and drop all tables.""" 
    db.drop_all() 

繼調試越往下我確定它最終得到這種方法self.traverse_single(table, drop_ok=True, _is_metadata_operation=True)

for table, fkcs in collection: 
    if table is not None: 
    self.traverse_single(table, drop_ok=True, _is_metadata_operation=True) 
    else: 
    for fkc in fkcs: 
    ... 

更具體。我假設它卡住等待發電機返回?不確定但在下面是我再次卡住之前得到的最後一行。

> /Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/SQLAlchemy-1.1.11-py3.6-macosx-10.7-x86_64.egg/sqlalchemy/sql/ddl.py(929)visit_table()->None 
-> _is_metadata_operation=_is_metadata_operation) 
(Pdb) n 
--Call-- 
> /Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/SQLAlchemy-1.1.11-py3.6-macosx-10.7-x86_64.egg/sqlalchemy/sql/visitors.py(150)_visitor_iterator()-><sqlalchemy.s...t 0x112045630> 
-> yield v 
(Pdb) n 
GeneratorExit 
> /Users/XXX/anaconda3/envs/XXX/lib/python3.6/site-packages/SQLAlchemy-1.1.11-py3.6-macosx-10.7-x86_64.egg/sqlalchemy/sql/visitors.py(150)_visitor_iterator()-><sqlalchemy.s...t 0x112045630> 
-> yield v 
(Pdb) l 
145   def _visitor_iterator(self): 
146    """iterate through this visitor and each 'chained' visitor.""" 
147  
148    v = self 
149    while v: 
150 ->    yield v 
151     v = getattr(v, '_next', None) 
152  
153   def chain(self, visitor): 
154    """'chain' an additional ClauseVisitor onto this ClauseVisitor. 
155  
(Pdb) n 

我相信它卡住礦井下表上

from ..helpers import get_current_time 
from ..extensions import db, ma 
from ..constants import STRING_LEN, DESCRIPTION_LEN 
from .worker import WorkerSchema 

class Injury(db.Model): 

    __tablename__ = "injuries" 
    def __repr__(self): 
    return '<Injury %r>' % (self.id) 

    id   = db.Column(db.Integer, primary_key = True) 
    title   = db.Column(db.String(STRING_LEN), nullable=False) 
    description = db.Column(db.String(DESCRIPTION_LEN), nullable=False) 
    worker_id  = db.Column(db.Integer, db.ForeignKey('workers.id')) 
    created_at = db.Column(db.DateTime, nullable=False, default = get_current_time) 
    updated_at = db.Column(db.DateTime, nullable=False, default = get_current_time, onupdate=get_current_time) 

    # Relationships 
    worker = db.relationship('Worker', back_populates='injuries') 

    # ================================================================ 

    # ================================================================ 
    # methods 


    # ================================================================ 
    # Class methods 

    @classmethod 
    def by_id(cls, id): 
    return cls.query.filter(Injury.id==id).first() 

class InjurySchema(ma.Schema): 
    class Meta: 
    fields = ('id', 'title', 'description', 'worker') 

    worker = ma.Nested(WorkerSchema) 
+0

當你遇到測試套件從未完成的問題時,鼻子會告訴你它正在運行的_which_函數嗎?如果是這樣,你可以編輯你的問題,包括輸出? –

+0

它沒有,我添加到我的帖子我的控制檯看起來像@JohnGordon,但除了我上面發佈的兩個之外,我還沒有其他測試 –

+0

在def之前的類方法函數中有一個縮進,是正確的嗎? – pyCthon

回答

4

我能得到它基於這個帖子SQLAlchemy blocked on dropping tables

def tearDown(self): 
    """Clean db session and drop all tables.""" 
    db.session.close() 
    db.drop_all() 
我drop_all命令前加 db.session.close()工作

我仍然需要找到爲什麼會議是開放的,我需要關閉它,但

相關問題