Tag: tests

  • Djangoのunit testをGitHubActionsで動かす

    この記事はこの記事は”東京高専プロコンゼミ① Advent Calendar 2019” 24日目の記事です.


    おはようございます, 記事を書いてる現在12/25 0時20分です.もう遅刻が当たり前になってきました. さて今日はようやくクリスマス・イブです,が アドベントカレンダーの枠を取ってしまったので記事を書いて行きます. 別にアドベントカレンダーを書いてるからクリボッチをしてるわけではないんですが


    今回の記事は前回のDjangoでtestsを書くはなしの続きです, まだ読んでないかたは適当に読み流してきてからこの記事を読むとわかりやすいかもしれません.

    GitHub Actions

    https://github.co.jp/features/actions

    GitHub Actionsってなんぞやって人のために一応説明しておくと, GitHub Actionsは設計図共有サイトであるGitHubが2019/11/13にリリースしたワークフロー自動化サービスです, これまではCircle CI などの外部サービスを使わないとできなかった高度なワークフローの自動化がGitHub内でできるようになりました. MSがGitHubを買収してからGitHubの新機能がすごい増えた気がします.

    値段とか

    基本的に無料で使えます. しかもLinuxだけじゃなくWindows, Macとかも動かせます. これまでWindowやmacOSが無料で使えるサービスはなかった気がするので, 結構大盤振る舞いです.

    設定

    設定はymlファイルでおこないます, β版のときはGUIエディターが用意されてたんですが, リリース版では廃止されています. 設定の書き方はCircle CIにすごい似てるらしいです.

    やりたいこと

    各Pushごとに前回の記事で書いたテストコードを自動で実行するようにします. そのためにはPythonの環境を揃えるのと, データベース(Postgresql)を立ち上げる必要があります.

    Python

    公式でtemplateが用意されてたのでそのファイルに書き込む形で作りました.

    Pythonのコンフィグはこんな感じになりました, 上の方で Pythonのパッケージをインストールしていて, 下の方で実際にテストを実行しています.

    DB(PostgreSQL)

    DjangoのtestはDBにアクセスするものもあるためDBを立てる必要があります, Exampleが公開されていたのでそれを流用しました.

    https://github.com/actions/example-services/blob/master/.github/workflows/postgres-service.yml

    最終的なConfig

    結果(?)

    動きました, 各pushごとにちゃんとテストを実行してくれます.

    PRを出すとそのPRでテストが通ってるかわかりやすく表示してくれます. 嬉しい!!

    まとめ

    GitHub Actions, 無料だし簡単に使えるので是非使いましょう. 毎回のPRでコーディング規約を守っているか, ビルドが通るかとかの確認くらいは来年のプロコンの開発で回せると(ある程度)安全な開発ができると思います.

  • Djangoでtestsを書く話

    この記事は東京高専プロコンゼミアドベントカレンダー②16日目の記事です。①の10日目の記事をまだ書いていない気がしますがきっと気の所為です、ええ。

    Djangoでtestsを書いてみたので記事にします。

    モチベーション

    去年のadvent calendarのネタとして作ったto2.pwをまだ動かしているのですがバグを直したり機能を追加するたびに全ての機能が問題なく動くか確認するという作業が発生して実際何度かインシデントを起こしたりしたのと、自分がメインの開発でテストコードを書くという経験をしたことがなかったので書いてみました。決してadvent calendarのための記事を書かないといけないからではない


    記事中で出てくるコードは大体ここにあるので全体が見たかったらどうぞ。

    testsとは?

    ここで言うtestsはソフトウェアテストのことです、ソースコード本体とは別にソースコードを”テスト”するためのコードを書き、自動で実行してバグの発生を防ぎます。最近では(?)ソースコード本体を書く前に仕様として満たすべき内容のテストを書き、その後開発するTDD(Test-Driven Development, テスト駆動開発)なる概念もあったりします。

    日本語でtestsと”s”を付けて書いたら学校の定期テストなどではなくソフトウェアの自動テストを指すことが多い気がします、Googleも”tests”を”ソフトウェアテスト”と認識してるっぽいです。

    Django

    Pythonで書けるweb frameworkです、全てのweb frameworkの中で一番高機能(or 高レイヤー)な気がします。初めから管理画面がユーザー認証が用意されていたりします。去年の課題部門ではDjangoを使った開発をしていたはずです、あと最近は使われてませんが(そもそも物をおいてないですが) 部内のpossysもDjangoを使って書かれてます。

    ちなみにDjangoは”ジャンゴ”と発音します、ディジャンゴとか発音すると大変恥ずかしいので気をつけましょう。。

    Djangoでunit testを書く

    正直Djangoのドキュメントぐう有能なのでドキュメントを参照してほしいんですが、なんとなくこんなことができるよ的なノリで参考程度にtestsの書き方を書いていきます。

    パス

    .
    ├── manage.py
    └── app
    ├── init.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    ├── models.py
    ├── tests.py
    ├── urls.py
    └── views.py

    Djangoでプロジェクトを作ったらだいたいこんな感じだと思いますが、tests.pyにテストを書き込んでいく、もしくは tests ディレクトリを作ってその中に test_hogehoge.pyを作っていくのが一般的っぽいです。ただ実行されるファイルはプロジェクト内のtest*.pyなのでそれさえ満たしてればなんでも良さそう。

    実行

    実行は

    python3 manage.py test

    で行います結果は
    “`

    Creating test database for alias 'default'...
    System check identified no issues (0 silenced).
    ..
    ----------------------------------------------------------------------
    Ran 5 tests in 0.083s
    
    OK
    Destroying test database for alias 'default'...

    みたいな感じで帰ってきます。

    書き方

    下の例では割り算をする関数division のテストコードを書いています。

    test_zero_divisionは0除算をしたとき-1を返すというdivision の仕様をテストしています。test_divisionは割り算が正しく行われるか調べています。asertEqual(a,b) というのはa=bのときテストが成功したと判断します。逆にa!=bだった場合テストに失敗したことを知らせてくれます。

    assert

    上の例でもあった通りテストは assert を使って書いていきます、assertは一致を確認するassertEqual 以外にも不一致を確認するassertNotEqual , Trueであることを確認するassertTrueなど色々な種類があります。もっと見たい人はunittestの公式ドキュメントを参照してください。

    mock

    testsを実行するのは実環境ではないのでどうしても実環境と違いがでてしまいうまくテストできない事が発生します。そんなときmockを使うと特定の関数の機能を上書きすることができます。実際 to2.pwではGoogleのrecaptchaを使っているのですがrecaptchaはunit testsでは再現できません、なのでmockを使いrecaptcha認証をしてるように見せ、テストコードを書きました。

    ↑ブラウザ上で発行されるtokenをgoogleに送信して認証するのでtestsでは実行できない

    @mock.patch('urlshortner.views._verifyRecaptcha', dummy_return_true) でurlshortner.views._verifyRecaptcha 関数を常にTrueを返すdummy_return_true 関数に置き換えて実行しています。

    client

    ちゃっかり上の例でも使ってたんですがtestClientを使うとAPIへのリクエストを再現できます。

    上の例だと/api/urls/に意図しないパラメータのリクエストが投げられたときのステータスコードとエラーメッセージを確認しています。

    まとめ

    いかがでしたか testsの概念となんとなくの書き方を知ってもらえたら幸いです。大体どの言語にもtests用のフレームワークがあると思うので個人で開発するときにテストを導入したり、今年はできなかったですがプロコンの開発にテストを導入することを検討して貰えればと思います(まあ半年間 or 一人開発のプロジェクトでどこまでテストを書く効果があるかわかりませんが…)