サービス側プログラミング(十五)-Django-自動化テスト入門


文書ディレクトリ

  • ´前言・ᴗ・`
  • 基本概念
  • 試験フレームワーク問題
  • テスト範囲テストルール--何をテストしたいですか?
  • 試験手順一覧
  • Authorモデル
  • のテスト
  • テストフォームforms
  • ビューのテスト
  • まとめ´◡`
  • 前言´・ᴗ・`

  • このセクションはスキップできますテストの勉強なので、あまり深く入り込む必要はありません.
  • 本当にseleniumを游びたいですこのフレームワークはもっと直感的でクライアント
  • に近いです.
  • 先の学习を経て、私达はすでにウェブサイトの主体を整备して残ったのはテストと少し美化の问题にほかならない私达はただとても小さい応用ですが、ページもすでに50枚以上(あなたの入力书の数によって)そんなに手动的にdebugに来て恐らく低効で面白くなくて、しかも漏れやすいこの时自动化のテストは
  • 使います
  • この内容はあなたの勉強を助けます...
  • 自動化テストの基本概念
  • 2 Djangoによる自動化テスト

  • 基本概念


    基本的ないくつかのテスト方法は次のとおりです.
  • ユニットはUnit testsをテストし、各コンポーネントの機能動作を検証し、通常はカテゴリと機能レベルである.
  • 回帰テストregression testsテスト再現履歴エラー.各テストを最初に実行して、エラーが修正されたかどうかを確認し、コードが後で変更された後にエラーが再導入されないことを確認します.
  • 統合テストintegration testsは、コンポーネントパケットが一緒に使用される場合の動作を検証します.統合テストは、コンポーネント間で必要なインタラクションを理解しますが、各コンポーネントの内部操作を理解する必要はありません.Webサイト全体の単純なコンポーネントグループをカバーする可能性があります.

  • テストフレームワークの問題


    また、Djangoのデフォルトではunitestを使用しています.もちろん、クラシックなseleniumなど、他の既存のテストフレームワークと統合して遊ぶことができます.この記事に興味があるのは、pythonアプリケーション(6)--爬虫類(1)seleniumの概要です.
    Googleにはjsベースの別のテストフレームワークがあります.これは現在の議論の範囲を超えています.もちろん、NodeJSを勉強するときにpuppeteerを遊ぶことができることを期待しています.

    テスト範囲テストルール--何をテストしたいですか?


    もちろんDjangoがパッケージ化されたアプリケーションをテストする必要はありません.肝心なのは私たちが書いたコードです.もちろん、私はmodelでlastを規定しています.name max_length=100はよく分からないと思いますか?なぜテストするの?
  • 原因1:私たちが開発するときに頻繁に需要を変更します.複数の人が協力して需要を変更します.私たちはテストルールを変更します.テストルールは需要に近いので、コードは言いにくいです.もし前に書いた「100」が他の人に変更されたとしたら?(チームワークの問題)あるいは先日変更して忘れたのですか?このフィールドがたくさんあれば問題は大きいと思いますgitでcommitが見えても保険はかかりません
  • 理由2 Djangoはあなたの予想通りに仕事をしないかもしれません.結局、いくつかのものが間違っていないのが最大の問題です.)
  • 要するにテストルールを作成するにはできるだけ詳しくしなければならない.

    テストプロセス一覧


    まずここではDjango内蔵のunitestライブラリを用いてテストを行うunitestが提供する多くのテストのパッケージをSimpleTestCase,TransactionTestCase,TestCase,LiveServerTestCaseなどにカプセル化して継承して運用しています
  • テストディレクトリを作成してテストカテゴリを決定します.私たちはすべてのモデルmodel/ビューview/フォームformsをテストします.そのため、カテゴリを分ける必要があります.ここでは、3つの一般ディレクトリに分けて設計します.
  • catalog/
      /tests/
        __init__.py
        test_models.py
        test_forms.py
        test_views.py
    

    テストルールファイルを置くためにtestsファイルを別途作成したtestが「テストキット」です__init__を見ると、キット内のファイルの名前に規範があるので、勝手に書いてはいけません.
  • テストファイルの作成(つまりテストツール)
  • 適切なテストクラスを継承してtestcaseを使いたいです.
  • from django.test import TestCase

  • テスト関数を定義この関数はmodelのフィールドまたはフォームの編集ボックスについて
  • 最初の関数の設計:テストケースtest Dataの作成
  • non-modifiedテストで変更されない定数例、例えば名前のようなsetUpTestData()
  • modifiedがテストで変化する変数の例、例えば変更される数字setUp()
  • .
  • 他の関数の設計、例えばdef test_false_is_false(self):
  • アサーションassertの設定も「expected」に似ています
  • AssertTrue理想状態この式はTrueテスト時にFalseにエラーを返す場合
  • AssertFalse,AssertEqual同理
  • assertRedirectsテスト
  • へのリダイレクトに成功したかどうか
  • assertTemplateUsedテストテンプレート
  • に使用されているかどうか


  • 実行テスト
  • すべてのテストpython manage.py test
  • を実行
  • testmodel:python3 manage.py test catalog.tests.test_modelsなどの特定のテストを実行し、テスト名testに注意する.catalog.test_modelこのフォーマットの書き方
  • 観察試験結果
  • >python3 manage.py test
    
    Creating test database for alias 'default'...
    setUpTestData: Run once to set up non-modified data for all class methods.
    setUp: Run once for every test method to setup clean data.
    Method: test_false_is_false.
    .setUp: Run once for every test method to setup clean data.
    Method: test_false_is_true.
    FsetUp: Run once for every test method to setup clean data.
    Method: test_one_plus_one_equals_two.
    .
    ======================================================================
    FAIL: test_false_is_true (catalog.tests.tests_models.YourTestClass)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "D:\Github\django_tmp\library_w_t_2\locallibrary\catalog\tests\tests_models.py", line 22, in test_false_is_true
        self.assertTrue(False)
    AssertionError: False is not true
    
    ----------------------------------------------------------------------
    Ran 3 tests in 0.075s
    
    FAILED (failures=1)
    Destroying test database for alias 'default'...
    

    2つのポイントについて説明します.
  • FAIL: test_false_is_true(catalog.tests.tests_models.YourTestClass)エラーはどこですか:test_flase_is_trueこの関数の
  • AssertionError:False is not trueどのように間違っています:理想的な状態はFalse実際にはTrue
  • です
    テストの過程を完全に理解することは期待していませんが、大体の印象を持ってください.
    次は実戦です.

    Authorモデルのテスト

    class Author(models.Model):
        first_name = models.CharField(max_length=100)
        last_name = models.CharField(max_length=100)
        date_of_birth = models.DateField(null=True, blank=True)
        date_of_death = models.DateField('Died', null=True, blank=True)
        
        def get_absolute_url(self):
            return reverse('author-detail', args=[str(self.id)])
        
        def __str__(self):
            return '%s, %s' % (self.last_name, self.first_name)
    

    元のモデルにどのような制限があるかを見てtest_を作成しますModelはAuthorModelTestをtestCaseを採用しています.
    from django.test import TestCase
    
    from catalog.models import Author
    
    class AuthorModelTest(TestCase):
    
        @classmethod
        def setUpTestData(cls):
            #Set up non-modified objects used by all test methods
            Author.objects.create(first_name='Big', last_name='Bob')
    
        def test_first_name_label(self):
            author=Author.objects.get(id=1)
            field_label = author._meta.get_field('first_name').verbose_name
            self.assertEquals(field_label,'first name')
    
        def test_date_of_death_label(self):
            author=Author.objects.get(id=1)
            field_label = author._meta.get_field('date_of_death').verbose_name
            self.assertEquals(field_label,'died')
    
        def test_first_name_max_length(self):
            author=Author.objects.get(id=1)
            max_length = author._meta.get_field('first_name').max_length
            self.assertEquals(max_length,100)
    
        def test_object_name_is_last_name_comma_first_name(self):
            author=Author.objects.get(id=1)
            expected_object_name = '%s, %s' % (author.last_name, author.first_name)
            self.assertEquals(expected_object_name,str(author))
    
        def test_get_absolute_url(self):
            author=Author.objects.get(id=1)
            #This will also fail if the urlconf is not defined.
            self.assertEquals(author.get_absolute_url(),'/catalog/author/1')
    

    ここでは、いくつかの点に注意してください.
  • assertTrueとassertEqualの問題test_first_name_label(self):つまり2番目の関数の末尾には、assertEquals(field_label,‘first name’)assertTrue(field_label=‘first name’)があります.フィードバック情報が多いので(first nameの実際の値を教えてください)
  • を推奨します.
  • フィールドラベル(verbose_nameと呼ばれる)の値と、文字フィールドのサイズが予想通りかどうかを確認します.author=Author.objects.get(id=1)#まずオブジェクトインスタンスfield_を取得label = author._meta.get_field(‘first_name’).verbose_name#フィールド名selfを取得します.assertEquals(field_label,‘first name’)#猫の虎のようにlastをテストできると断言nameなどのフィールド
  • フォームformsのテスト


    実はテストモデルとあまり差がありません.私たちの図書館の応用は主にレンタル日です.これは元のformsをテストする必要があります.pyコード:
    class RenewBookForm(forms.Form):
        """
        Form for a librarian to renew books.
        """
        renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).")
    
        def clean_renewal_date(self):
            data = self.cleaned_data['renewal_date']
    
            #Check date is not in past.
            if data < datetime.date.today():
                raise ValidationError(_('Invalid date - renewal in past'))
            #Check date is in range librarian allowed to change (+4 weeks)
            if data > datetime.date.today() + datetime.timedelta(weeks=4):
                raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead'))
    
            # Remember to always return the cleaned data.
            return data
    

    これに対して、次のテストコードを設計しました.
  • labelフォームに表示されるラベルテスト
  • help_textフォームに表示されるヘルプ情報
  • 入力日付の範囲が今後4週間以内にtimedelta関数datetimeに注意するかどうか.timedelta(days=2)は2日間の時間差weeks=4が周囲の時間差
  • であることを指す.
    /catalog/tests/test_forms.py
    from django.test import TestCase
    
    # Create your tests here.
    
    import datetime
    from django.utils import timezone
    from catalog.forms import RenewBookForm
    
    class RenewBookFormTest(TestCase):
    
        def test_renew_form_date_field_label(self):
            form = RenewBookForm()        
            self.assertTrue(form.fields['renewal_date'].label == None or form.fields['renewal_date'].label == 'renewal date')
    
        def test_renew_form_date_field_help_text(self):
            form = RenewBookForm()
            self.assertEqual(form.fields['renewal_date'].help_text,'Enter a date between now and 4 weeks (default 3).')
    
        def test_renew_form_date_in_past(self):
            date = datetime.date.today() - datetime.timedelta(days=1)
            form_data = {'renewal_date': date}
            form = RenewBookForm(data=form_data)
            self.assertFalse(form.is_valid())
    
        def test_renew_form_date_too_far_in_future(self):
            date = datetime.date.today() + datetime.timedelta(weeks=4) + datetime.timedelta(days=1)
            form_data = {'renewal_date': date}
            form = RenewBookForm(data=form_data)
            self.assertFalse(form.is_valid())
    
        def test_renew_form_date_today(self):
            date = datetime.date.today()
            form_data = {'renewal_date': date}
            form = RenewBookForm(data=form_data)
            self.assertTrue(form.is_valid())
            
        def test_renew_form_date_max(self):
            date = timezone.now() + datetime.timedelta(weeks=4)
            form_data = {'renewal_date': date}
            form = RenewBookForm(data=form_data)
            self.assertTrue(form.is_valid())
    

    ここで、転送データはキー値ペアの形式を採用し、この「renewal_date」は確かにクラス属性に由来し、クラスインスタンスのis_valid()を呼び出してテストを断言します.
            date = datetime.date.today() - datetime.timedelta(days=1)
            form_data = {'renewal_date': date}
            form = RenewBookForm(data=form_data)
            self.assertFalse(form.is_valid())
    

    ビューのテスト


    ここでauthorの検証を例に挙げると、実際に私たちの多くの仕事はdjangoに検証する必要はありません.ここでは栗/catalog/tests/test_を挙げるだけです.views.py
    from django.test import TestCase
    
    # Create your tests here.
    
    from catalog.models import Author
    from django.urls import reverse
    
    class AuthorListViewTest(TestCase):
    
        @classmethod
        def setUpTestData(cls):
            #Create 13 authors for pagination tests
            number_of_authors = 13
            for author_num in range(number_of_authors):
                Author.objects.create(first_name='Christian %s' % author_num, last_name = 'Surname %s' % author_num,)
               
        def test_view_url_exists_at_desired_location(self): 
            resp = self.client.get('/catalog/authors/') 
            self.assertEqual(resp.status_code, 200)  
               
        def test_view_url_accessible_by_name(self):
            resp = self.client.get(reverse('authors'))
            self.assertEqual(resp.status_code, 200)
            
        def test_view_uses_correct_template(self):
            resp = self.client.get(reverse('authors'))
            self.assertEqual(resp.status_code, 200)
    
            self.assertTemplateUsed(resp, 'catalog/author_list.html')
            
        def test_pagination_is_ten(self):
            resp = self.client.get(reverse('authors'))
            self.assertEqual(resp.status_code, 200)
            self.assertTrue('is_paginated' in resp.context)
            self.assertTrue(resp.context['is_paginated'] == True)
            self.assertTrue( len(resp.context['author_list']) == 10)
    
        def test_lists_all_authors(self):
            #Get second page and confirm it has (exactly) remaining 3 items
            resp = self.client.get(reverse('authors')+'?page=2')
            self.assertEqual(resp.status_code, 200)
            self.assertTrue('is_paginated' in resp.context)
            self.assertTrue(resp.context['is_paginated'] == True)
            self.assertTrue( len(resp.context['author_list']) == 3)
    

    ここではまず彼がページを分けて13のデータを作ったかどうかを検証します.
    number_of_authors = 13
            for author_num in range(number_of_authors):
                Author.objects.create(first_name='Christian %s' % author_num, last_name = 'Surname %s' % author_num,)
    

    あとで断言する
            self.assertTrue('is_paginated' in resp.context)
            self.assertTrue(resp.context['is_paginated'] == True)
            self.assertTrue( len(resp.context['author_list']) == 10)
    
    

    さらに重要なのはurlマッピングとreverse逆マッピングをテストすることですclient.get実装:)
        def test_view_url_exists_at_desired_location(self): 
            resp = self.client.get('/catalog/authors/') 
            self.assertEqual(resp.status_code, 200)  
               
        def test_view_url_accessible_by_name(self):
            resp = self.client.get(reverse('authors'))
            self.assertEqual(resp.status_code, 200)
    

    まとめ´◡`


    自動化テストはまた1つの大学が個人に聞くのは先に焦らないで勉強します
  • このコラムMySQLコラム
  • 私の他のコラムはあなたを助けたいと思っています(•̀ ω •́ )✧
  • ハンドル学習バックエンド(サービス側)
  • pythonこんなに火がついてpythonを深く勉強して簡単な応用をしたいですか?pythonアプリケーション
  • ありがとうございます!萌新有礼:)