Django BDD開発

プログラマーはテストに対して非常に異なった態度を持ち、多くはテストを書くことを好みません。 TDDプロセスは初心者にとって特に明確ではありません。プログラムの機能の代わりに、最初にそれをチェックするテスト、つまり作業量が増加するテストを作成する必要があるためです。 ただし、時間が経つにつれて、自動テストが必要であるという認識が生まれます。 たとえば、単純なdjangoプロジェクトの開発プロセスを取り上げますが、プロジェクトにはいくつかのビューとモデルがありますが、すべてが単純です。 アプリケーションが機能で過負荷になると、そのようなテストを実行することがより困難であることが突然判明します-より多くのクリックがあり、いくつかのデータを入力する必要があります。



画像



サイトのランキング-プリミティブアプリケーションを作成する例としてBDDについてお話します。 アイデアは簡単です-ページにサイトのリストが表示され、ユーザーがサイトに投票すると、サイトのランキングが上がり、それに応じてページ上の位置が変わります。



まず、プロジェクトの作業フォルダーにrequirements.txtを作成します。おおよそ次のコンテンツが含まれます。
Django git+git://github.com/svfat/django-behave splinter
      
      







開発ではフォークdjango-behaveを使用していることに注意してください。 公式リポジトリのコードは、明らかに現在のバージョンのプログラムとの非互換性のため、動作を拒否しました。
 $ pip install -r requirements.txt $ django-admin.py startproject habratest $ cd habratest/ $ ./manage.py startapp vote
      
      







デフォルトでは、最新の安定版のDjangoをインストールする必要があります。開発を開始するには、settings.pyに数行を追加するだけです。
 INSTALLED_APPS = ( ... 'vote', 'django_behave', ) TEMPLATE_DIRS = ( os.path.join(BASE_DIR, 'templates/'), #     habratest/templates ) TEST_RUNNER = 'django_behave.runner.DjangoBehaveTestSuiteRunner'
      
      







最初のステップは、サイトのリストを表示することです。 使用しているツールを使用してBDDスタイルで開発するには、habratest / vote / featuresおよびhabratest / vote / features / stepsフォルダーを作成します



ここでは、アプリケーションから達成したい動作について説明します。 featuresフォルダーで、次の内容のhabra.featuresファイルを作成します。
 Feature: Habrarating Scenario: Show a rating Given I am a visitor When I visit url "http://localhost:8081/" Then I should see link contents url "habrahabr.ru"
      
      







本当にコンピューター言語とは違いますか? これはガーキンです。 その上で、実装に入らずにプログラムの動作を説明できます。 したがって、プログラミングに精通した人はテストタスクを書くことができます。



django-behaveはポート8081でテストサーバーを起動するため、このURLを指定します。



同じフォルダーに、テストの前後に実行されるコードであるenvironment.pyを作成します。これまでのところ、テストブラウザーの機能のみが保証されます。
 from splinter.browser import Browser def before_all(context): context.browser = Browser() def after_all(context): context.browser.quit() context.browser = None
      
      







打ち上げ
 $ ./manage.py test vote
      
      







何も起こりませんでした-テスト環境はhabra.featuresファイルのステップをどうするかを理解していません黄色(よく、または茶色黄色)の線を見てください。 それらをhabratest / vote / features / steps / habra.feature.pyに自由にコピーしてください。手順の実装について説明し、その内容は次のようになります。
 from behave import given, when, then @then(u'I should see link contents url "{content}"') def i_should_see_link_contents_url(context, content): msg = context.browser.find_link_by_partial_href(content).first assert msg @when(r'I visit url "{url}"') def i_visit_url(context, url): br = context.browser br.visit(url) @given(u'I am a visitor') def i_am_a_visitor(context): pass
      
      







もう一度走る
  $ ./manage.py test vote
      
      







したがって、テストが失敗することを確認する必要があります。その理由は明らかです。アプリケーションの機能コードを1行も記述しておらず、データベースにデータがありません。



vote / models.pyでモデルを作成します
 class VoteItem(models.Model): url = models.URLField() rating = models.IntegerField(default=0) class Meta: #      ListView      ordering = ["-rating"] def __unicode__(self): return self.url
      
      







私たちはやる:
 $ ./manage.py syncdb
      
      







habratest / urls.pyでインポートします
 from vote.views import VoteListView
      
      







urlpatternsに追加します
  url(r'^$', VoteListView.as_view(), name="index"),
      
      







投票中/ views.py
 from django.views.generic import ListView from models import VoteItem class VoteListView(ListView): model=VoteItem template_name="list.html"
      
      







habratest / templates / list.htmlのレトロなスタイルのテンプレート:
 <!DOCTYPE html> <html> <head> <title>Habra rating</title> </head> <body> <ol> {% for voteitem in object_list %} <li id="{{voteitem.pk}}"><a href="{{ voteitem.url }}">{{ voteitem.url }}</a> | Rating:{{voteitem.rating}}</li> {% endfor %} </ul> </body> </html>
      
      







テストを実行すると、毎回メモリに新しいデータベースが作成され、終了後に削除されるため、データを入力する必要があります。 このためには、ファイルhabratest / habratest / populate.pyに次のように記述します。
 from vote.models import VoteItem VoteItem(url="http://www.yandex.ru", rating=6).save() VoteItem(url="http://www.google.com", rating=5).save() VoteItem(url="http://www.habrahabr.ru", rating=6).save()
      
      







このスクリプトのインポートをenvironment.pyに追加します
 from habratest import populate
      
      







現在、environment.pyは、ブラウザの動作を保証することに加えて、テストベースにも関与しています。



もう一度始めます
 $ ./manage.py test vote
      
      







-すばらしい、テストは合格しました。しかし、評価についてはどうでしょう-サイトに何らかの形で投票する必要があります



新しいスクリプトをhabra.featureに追加します。
  Scenario: Vote for a site Given I am a visitor When I visit url "http://localhost:8081/" When I click link contents "+" Then I should see "Vote successful" somewhere in page
      
      







テスト環境では、最後の2つのステップを完了する方法がわからないため、steps / habra.feature.pyに追加します。
 @then(u'I should see "{text}" somewhere in page') def i_should_see_text_somwhere_in_page(context, text): assert text in context.browser.html @when(u'I click link contents "{text}"') def i_click_link_contents_text(context, text): link = context.browser.find_link_by_text(text).first assert link link.click()
      
      







次に、テストを再度実行します。 リンクコンテンツ「+」をクリックすると、ステップのエラーが発生します。 そのため、テンプレートには「+」リンクがありません。これに対する反応がないため、次のように修正します(コードが不正行為から保護されていないことに注意してください。これは単なる例です)。



habratest / templates / list.htmlにプラスを追加します:
 <li id="{{voteitem.pk}}"><a href="{{ voteitem.url }}">{{ voteitem.url }}</a> | Rating:{{voteitem.rating}} | <a href={% url 'addvote' voteitem.pk %}>+<a></li>
      
      







したがって、vote / views.pyでaddvoteのプリミティブビューを作成します。
 from django.shortcuts import render_to_response def addvote(request, pk): return render_to_response('successful.html', context)
      
      







urls.pyに追加し、
 from vote.views import VoteListView, addvote
      
      







そして
  url(r'^plus/(?P<pk>\d+)/$', addvote, name='addvote'),
      
      







そして、テンプレートテンプレート/successful.html:
 <!DOCTYPE html> <html> <head> <title>Habra rating</title> </head> <body> <p>Vote successful</p> </body> </html>
      
      







テストを実行します-すべてが成功するはずです。



そして、評価を上げるパフォーマンスをテストするテストを作成します。 投票中にリストの変更が表示されるはずです。ここでは、y habrahabr.ruの評価= 6であるため、ソースデータ(populate.pyに対して作成された)を知っているという事実を利用します。前のシナリオによると、その評価は「7」に等しくなければなりません。
  Scenario: Vote for a site and look at the rating Given I am a visitor When I visit url "http://localhost:8081/" Then I should see "Rating:7" somewhere in page
      
      







繰り返しますが、最後のステップは実行されません。 これを修正するには、addvoteビューを追加します。
 def addvote(request, pk): item = VoteItem.objects.get(pk=pk) item.rating += 1 item.save() return render_to_response('successful.html')
      
      







テストが成功したことを確認します。



そのため、ガーキンのテスト(上記で述べたように、プログラミングに不慣れな人でもできる)を書き続けることで、実際に技術的なタスクの一部を作成し、同時にアプリケーションの受け入れテストを行います。



ロシア語ではdjangoを使用したBDDに関する情報はほとんどないので、この記事を書きました。この問題の専門家が突然それを読んだとしても、怠けてはいけません。 誰にとっても役立つでしょう。 あなたのコメント、訂正、批判を喜んで受け入れます。 よろしくお願いします!



他に読むもの:

動作するドキュメント

Splinter-Webアプリケーションのテストフレームワーク

DjangoのフルスタックテストとBDDとLettuceおよびSplinter




All Articles