Djangoプロゞェクトのテストの高速化

Djangoアプリケヌションのテストの問題は、Habréを含むさたざたな蚘事で倧きな泚目を集めおいたす。 それらのほがすべおにおいお、テストの合栌を高速化するためのメ゜ッドずハックに少なくずも2、3の文が圓おられおいるため、ここで根本的に新しいこずを蚀うのは容易ではありたせん。



NetAngelsでほずんどの時間を費やしおきたホスティングコントロヌルパネルのプロゞェクトでは、テスト䞭に120個のテヌブルずフィクスチャからの玄500個のオブゞェクトがロヌドされたす。 これは恐ろしいほど倚くは蚀えたせんが、すべおのテヌブルを䜜成し、テストを実行するたびにむンデックスを远加し、オブゞェクトをロヌドするこずは、特に1぀たたは2぀だけのテストを実行する堎合は非垞に面倒です。



猫の䞋では、以前に提案されたテストを高速化するためのいく぀かの方法がやや簡朔にリストされおおり、最埌に別の有甚なレシピの詳现な説明がありたすが、私は今、テスト実行の速床の問題をすでに完党に陀去しおいるこずを願っおいたす。



平均的なアプリケヌションでは、原則ずしお、ほずんどのブレヌキはデヌタベヌスの操䜜に関連付けられたす。 ほずんどすべおの提案がこの特定のコンポヌネントの最適化を目的ずしおいるこずは驚くこずではありたせん。



次に、デヌタベヌスの操䜜は䞻にディスクサブシステムによっお遅くなりたす。この負荷を䜕らかの方法で削枛するず、パフォヌマンスが倧幅に向䞊するず想定するのは理にかなっおいたす。



安党でないトランザクション蚭定



テストプロセス䞭に電気が突然倱われ、デヌタがディスクに完党に曞き蟌たれない堎合、誰も気にしたせん。 通垞、デヌタベヌスサヌバヌは、このようなむベントの悲しい結果を最小限に抑えるように構成されおいたす。 テスト甚に別のMySQLサヌバヌたたはPostgreSQLサヌバヌを䜿甚する堎合、蚭定を安党に安党に倉曎できたす。



特に、MySQLの堎合、以䞋を提䟛したす。



[mysqld]

default-table-type=innodb

transaction-isolation=READ-COMMITTED

innodb_flush_log_at_trx_commit = 0

skip-sync-frm=OFF









PostgreSQLでは、同じ目的でpostgresql.confにfsync = off



オプションを远加するこずをお勧めfsync = off



たす。



ramdiskを䜿甚する



より根本的なアプロヌチは、ディスクをたったく䜿甚せず、代わりにRAM内のデヌタを操䜜するこずです。 䞀般的な原則は、tmpfsファむルシステムを䜿甚しお新しいパヌティションを䜜成し、別のディレクトリにマりントしおから、すべおのデヌタベヌスファむルをこのディレクトリに䜜成するこずです。 远加のボヌナスは、単にパヌティションをアンマりントするずすべおのデヌタが削陀されるこずです。



テスト甚のSQLite



実際、Django開発者は、テストをできるだけ早く実行するために倚くのこずをすでに行っおいたす。 特に、SQLiteをデヌタベヌス゚ンゞンずしお䜿甚する堎合、テスト䞭にデヌタベヌスがメモリに䜜成され文字列 "memory"がファむル名ずしおドラむバに枡されたす、この方法だけでほずんどの問題を高速で解決できたす。



ORM Djangoがデヌタベヌスの詳现を慎重に隠しおいないず䞍平を蚀うこずもあるため、堎合によっおは、SQLiteで機胜するコヌド぀たり、テストに合栌したコヌドが、それが存圚するシステムにロヌルアりトするず突然壊れるこずがありたすMySQLは動䜜したす。 実際、これは時々起こりたすが、原則ずしお、あなたが䜕か「異垞な」こずをしたずいう事実の結果です。䟋えば、QuerySet.extraメ゜ッドを䜿甚しお手動でク゚リを䜜成し始めたした。 ただし、ほずんどの堎合、そのようなこずをすれば、これがどのように脅嚁になるかを知っおいたす。



予備のSQLiteテストベヌスの䜜成



ご存知のように、テストを実行するず、Djangoは次の䞀連のアクションを実行したす。



1.ナヌザヌの蚱可を埗お、テストデヌタベヌスをクリアしたすテストデヌタベヌスに䜕かがある堎合

2.テストデヌタベヌスにすべおのテヌブルずむンデックスを䜜成したす

3. initial_dataずいう䞀連のフィクスチャをロヌドしたす

4.テストを1぀ず぀実行したす

5.テスト䞭に䜜成されたすべおを削陀したす



デヌタがメモリ内に存圚する堎合、最初ず最埌のステヌゞは実行されない可胜性がありたすが、ステップ2ず3にはかなりの時間がかかり、「コヌドを修正しおテストを開始」ずいう高速の反埩が遅くなりたす。 明らかに、デヌタベヌススキヌマずフィクスチャセットは、コヌドずテストよりもはるかに少ない頻床で倉曎されるため、デヌタベヌスの絶え間ない䜜成を節玄するこずには意味がありたす。 ちなみに、ステップ2ず3は、syncdb管理コマンドの通垞の実行です。



テストの実行を高速化する䞀般的なアプロヌチは、syncdbを手動で実行するこずです。本圓に必芁な堎合にのみ、テストを開始するずきに準備枈みのデヌタベヌスをコピヌするだけです。 SQLiteを䜿甚するず、ファむルをコピヌせずに実行できたすが、「memory」でテストを操䜜する利点を倱いたくありたせんでした。



短い怜玢により、このケヌスの解決策が存圚するこずが瀺されたした。 SQLiteには「ホット」バックアップ甚のむンタヌフェむスがあり倧人の堎合ず同様、事前に準備されたデヌタベヌスからそのようなコピヌを名前がmemoryのデヌタベヌスに実行するず、たさに必芁なものが埗られたす初期化されたデヌタベヌスメモリ内のデヌタ。



実装の最初の難しさは、暙準のPythonモゞュヌルsqlite3がサポヌトしおおらず、おそらくこのAPIをサポヌトしないこずです。したがっお、Pythonを䜿甚しおこのようなコピヌを実行するには、APSWAnother Python SQLite Wrapperずいうサヌドパヌティモゞュヌルを䜿甚するこずをお勧めしたす。



2番目の難点は、メモリ内の新しいデヌタベヌス接続ごずに、デヌタベヌスの独自のコピヌ明らかに空を䜜成するため、ORSWが䜿甚するカヌ゜ルにAPSWによっお初期化された接続を䜿甚する方法を教える必芁があるこずです。 幞いなこずに、この堎合にはハックが提䟛されたす。sqlite3を䜿甚しお接続を䜜成するずきに、ファむル名のある行の代わりに、apsw.Connectionオブゞェクトを枡すこずができたす。



そのため、゜リュヌションは非垞にシンプルに芋えたす。



1. 2぀のASPW接続オブゞェクトを䜜成したす。1぀は事前に準備されたデヌタベヌスを参照し、もう1぀はメモリ内のデヌタベヌスを参照したす。

2.ファむルからメモリにデヌタをコピヌしたす。

3.「default」ずいう名前の゚むリアスのNAMEパラメヌタヌには、メモリを参照するASPW接続を枡したす。

4.カヌ゜ルを初期化し、テストを実行したす。



デヌタベヌスの䜜成は非垞に簡単です。「quickstart」ずいう名前の゚むリアスをDATABASES settings.py倉数に远加しおから、. ./manage.py syncdb --database quickstart



実行する./manage.py syncdb --database quickstart



です。



これらのアクションを実行できるすべおのコヌドは、20行匱かかり、以䞋に瀺したす。 動䜜させるには十分です



1. APSWをむンストヌルしたす

2.コヌドを別のファむルにコピヌしお、プロゞェクトに配眮したす

3. quickstartずいう名前のデヌタベヌスのsettings.DABABASESに゚むリアスを远加したす

4. ./manage.py syncdb --database quickstart



実行しおデヌタベヌスを䜜成したす

5.倉数TEST_RUNNERを蚭定しお、保存したばかりのオブゞェクトのクラスを参照するようにしたす

6.簡単なテストを実行しおみおください。



Copy Source | Copy HTML



  1. むンポヌト apsw
  2. ゞャンゎから 。 テスト .simple import DjangoTestSuiteRunner
  3. django.db むンポヌト接続から
  4. クラス TestSuiteRunner DjangoTestSuiteRunner
  5. def setup_databases self、** kwargs
  6. quickstart_connection = connections [ 'quickstart' ]
  7. quickstart_dbname = quickstart_connection.settings_dict [ 'NAME' ]
  8. memory_connection = apsw.Connection 'メモリ' 
  9. quickstart_connection = apsw.Connectionquickstart_dbname
  10. バックアップずしお memory_connection.backup 'main' 、quickstart_connection、 'main'  を䜿甚したす。
  11. backup.doneではない堎合
  12. backup.step 100 
  13. connection = connections [ 'default' ]
  14. connection.settings_dict [ 'NAME' ] = memory_connection
  15. カヌ゜ル= connection.cursor
  16. def teardown_databases self、old_config、** kwargs
  17. 合栌する




その結果、1぀のテストの実行時間が18秒から2秒に短瞮されたした。必芁な回数だけテストを実行するのは非垞に快適です。



同じコヌドですが、コメントず「テストでデヌタが食べられる可胜性がありたす」テスト環境でのみ䜿甚ずいう倧胆な譊告がgist.github.com/1044215で利甚可胜です。



これらの簡単な掚奚事項により、コヌドをより速く、より効率的に、より確実に曞くこずができればず思いたす。



䜿甚した゜ヌス



詳现およびその他の有甚な情報に぀いおは、デヌタベヌスサヌバヌのドキュメントず次の゜ヌスを参照するこずをお勧めしたす。



-MySQLを䜿甚したDjangoナニットテストの実行の高速化

-Innodbパフォヌマンス最適化の基本

-SQLite Online Backup APIの䜿甚

-PythonでSQLiteのバックアップを䜿甚する方法



All Articles