2017-01-25 11 views
0

私がfake_user's(FactoryBoy経由で作成)usernameがすでに存在するかどうかをテストする簡単なユニットテストを作成しようとしています。 (つまり、誰かが既に同じユーザー名でユーザーを作成しています)。str型オブジェクトでassertRaises()を正しく使用する方法

テストの簡易版は次のようになります:

# factories.py 
import factory 


class BaseUserFactory(factory.DjangoModelFactory): 
    """A factory for creating User objects.""" 

    username = factory.Faker('word') 
    email = factory.lazy_attribute(lambda x: '%[email protected]' % (x.username)) 

    class Meta: 
     """User factory Meta attributes.""" 

     model = models.User 
     django_get_or_create = ('username', 'email') 

簡単なテスト:

#test_user.py 
from django.test import TestCase 
from django.apps import apps 

from . import factories 


class TestAccountModels(TestCase): 
    """Testing the User models.""" 

    users = [user.username for user in models.User.objects.all()] 
    fake_user = factories.BaseUserFactory.create() 

    def test_username_available(self): 
     self.assertIn(self.fake_user.username, self.users) 

今文脈のために、私の(既存の)username(s)は「ブロディと言います'と'サム '。 test_username_availableの実行は、私は戻って取得する場合:

self.assertIn(self.fake_user.username, self.users) 
AssertionError: 'suscipit' not found in ['Sam', 'Brody'] 

私の質問はこれです:

は、私は、この特定のエラーのためにテストするためのテストを書きたいです。

def test_clean_username(self): 
    self.assertRaises(
     AssertionError, '"{0}" unexpectedly found in "{1}"'.format(
      self.proposed_username, 
      self.taken_usernames, 
      ) 
     ) 

けど(taken_usernames上)str object is not callableを得続ける;:私はこのような何かを試してみましたそして私はそれを得るが、ちょうどカントは

回避策を見つけるように見える:私は再作業このさまざまな方法を試してみたが、問題は、別の答えから(これにリンクされているようだ

proposed_username = self.fake_user.username 
self.taken_usernames = [self.user.username for self.user in self.user] 

を私はこれをどこかに書き留めましたので、残念なことにリンクはありません):

You are using self.assertRaises() incorrectly. 
It has to call the test function for you, in order to catch the exception 
self.assertRaises(mouse16.BadInternalCallException, 
stack.insertn, [8, 4, 12], 16) 

You were passing in the result of the stack.insertn() call (which didn't raise an exception, but returned either None or an integer instead), and that return value is not callable. 
An older version of the method accepted None for that argument as well, which is no longer supported, hence the deprecation warning when None is passed in versus an integer. 
The better way is to use self.assertRaises() as a context manager: 
with self.assertRaises(mouse16.BadInternalCallException): 
stack.insertn([8, 4, 12], 16 

私はコンテキストマネージャを使用する必要がありますか?私はこれがより簡単になるべきであると感じて、私はそれをもっと難しくしています。もともと、私はモデルから属性を取り出そうとしていました。 dictしかし、誰かがelsesのアドバイスを取ってしまい、リストの理解力を使いました。

これはTestCaseメソッド/クラスの外で動作します。私はこれのための簡単な修正が必要があると思うpython/djangoの私の知識はちょうどそこにかなりありません。

ありがとうございました!

編集:以下の回答は有望だと思われますが、関係なく通過するようです。正規表現の完全な一致は、以下のように

+0

しかし、あなたはassertRaisesにどんな種類の関数も渡しているようではなく、ちょうど2組のユーザー名を渡しているようです。あなたは何を期待していますか? –

+0

とにかく、なぜ別のテストで発生したエラーをテストしたいのですか? –

+0

それで、私は2番目のテスト自体をしたくありません。私は、この特定のエラーのテストは、xyzがabcに存在するかどうかを調べるテストよりも優れていると考えていました。これは代わりに、エラーの代わりにテストするより良い練習だったと思った。 – srylotsquestions

答えて

0

assertRaises使用率が見えます(つまり、エラー・メッセージ)および(AssertionErrorが、この場合は)エラータイプが存在しない限り、私は失敗するテストが欲しい:

self.assertRaises(InvalidOperation, Decimal, '25,34') 

引数argsとキーワード引数kwargsで呼び出されたときに、callableObj によってクラスexcClassの例外が発生しない限り、失敗します。

Decimalはcallableであり、'25,34 'はargです。あなたのケースの使用assertRaisesMessageで

def test_clean_username(self): 
    self.assertRaisesMessage(
     AssertionError, '"{0}" unexpectedly found in "{1}"'.format(
      self.proposed_username, 
      self.taken_usernames, 
     ) 
    ) 

はexpected_messageが上がっ 例外のメッセージに発見されたと主張しています。

+0

これは有望そうです...説明をありがとうございます 私が弦で何を持っているかにかかわらず?たとえば、私は '予期せぬことに'から 'yoyoyo'に切り替わります。なぜなら、それは次の理由によるものです。 発生した例外のメッセージにexpected_messageがあると主張します。 メッセージに存在するのでその通りですか?私は多かれ少なかれ正確な一致を探しています – srylotsquestions

+0

実装内を見ると、assertInが使用されます。メッセージ 'test'と例外 'xxx test yyy'を予期していたら、テストには正確なメッセージを使用してください。 –

+0

あなたはそれをテストしましたか? –