PhoenixとElixirを使用してブログエンジンを作成する/パート5. ExMachinaを接続する



翻訳者から:「 エリクサーとフェニックスは、最新のウェブ開発がどこに進んでいるかの良い例です。 すでにこれらのツールは、Webアプリケーションのリアルタイムテクノロジーへの質の高いアクセスを提供します。 対話性が向上したサイト、マルチユーザーブラウザーゲーム、マイクロサービスは、これらの技術がうまく機能する分野です。 以下は、Phoenixフレームワークでの開発の詳細な側面を説明する一連の11の記事の翻訳です。ブログエンジンのような些細なことのように思えます。 しかし、急いでつまずかないでください。特に記事がエリクサーに注意を払うか、彼のフォロワーになるように促す場合、それは本当に面白いでしょう。

この部分では、ExMachinaライブラリを含めて、テストプロセスを改善します。 テストしたモデルを作成するために同一のコードをコピーする必要はありません。工場が私たちのためにそれを行います!

現時点では、アプリケーションは以下に基づいています。


はじめに


お気づきのように、このエンジンを作成するプロセスでは、いくつかのライブラリのみを使用します。 次に、ExMachinaと呼ばれる別のものを追加します。 彼女は、RubyのFactory Girlに類似しています。

これは何?


前述のように、ExMachinaは、RubyのFactoryパターン(Thoughtbotのすばらしい人物による)の実装であるFactory Girlのイメージで設計されています。 コードを書き直さずにテストを作成することなく、リレーションシップを持つさまざまなモデルをテストに追加することは素晴らしいことです。 モデルを生成するための単純な関数を含む補助モジュールを使用して、同じことを自分で達成できます。 しかし、それはすべて、必要なデータセットごと、通信ごとなどに、そのようなモジュールを絶えず作成することに帰着します。 これには確かに退屈する時間があります。

降りる


mix.exsmix.exsファイルを開いて、 depsおよびapplicationリストに追加します。 これを行うには、ExMachinaの別のエントリをComeOnInの直後の依存関係のリストに挿入します。

 defp deps do [{:phoenix, "~> 1.2.0"}, {:phoenix_pubsub, "~> 1.0"}, {:phoenix_ecto, "~> 3.0"}, {:postgrex, ">= 0.0.0"}, {:phoenix_html, "~> 2.6"}, {:phoenix_live_reload, "~> 1.0", only: :dev}, {:gettext, "~> 0.11"}, {:cowboy, "~> 1.0"}, {:comeonin, "~> 2.5.2"}, {:ex_machina, "~> 1.0"}] end 

次に、使用されているアプリケーションのリストに:ex_machinaを追加します。

 def application do [mod: {Pxblog, []}, applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext, :phoenix_ecto, :postgrex, :comeonin, :ex_machina]] end 

次のコマンドを実行して、アプリケーションコンポーネントの準備ができ、正しく構成されていることを確認します。

 $ mix do deps.get, compile 

すべてがうまくいけば、ExMachinaのインストールとプロジェクトのコンパイルに関するメッセージが出力に表示されるはずです! コードの変更を開始する前に、 mix testを実行し、信頼性を高めるために、すべてのテストがグリーンであることを確認する必要があります。

ロールの最初のファクトリーを追加します


ファクトリモジュールを作成し、すべてのテストで使用できるようにする必要があります。 私はテストを膨らませることなくこれを行うことを好みます。 これを行うには、ファクトリを含むモジュールファイルをtest/supportディレクトリにドロップし、必要なテストでそのインポートを記述します。

それでは、ファイルtest/support/factory.ex作成することから始めましょう:

 defmodule Pxblog.Factory do use ExMachina.Ecto, repo: Pxblog.Repo alias Pxblog.Role alias Pxblog.User alias Pxblog.Post def role_factory do %Role{ name: sequence(:name, &"Test Role #{&1}"), admin: false } end end 

このような名前はこのモジュールの本質を反映しているため、これをFactoryと呼びました。 次に、特別なファクトリー関数を使用します。 これらは、入力に供給されたアトムをサンプルと比較し、 アセンブル / 作成するファクトリのタイプを決定します 。 このライブラリはFactory Girlに非常に近いため、知っておくべき重要な命名規則ももたらします。 最初のそのような名前はbuildです。 build機能とは、データベースに保存せずにモデル( リビジョンではなく)がbuildことを意味します。 2番目の規則は、 insert関数の名前になります。反対に、モデルはデータベースに格納され、それによってモデルが作成されます。

また、ExMachinaがEctoをレポレイヤーとして使用し、モデル、関連付けなどの作成時にそれに応じて動作するように、ExMachina.Ectoの使用を指定use ExMachina.Ecto必要があります。 また、ファクトリを作成するすべてのモデルにエイリアスを追加する必要があります。

role_factory関数は、デフォルトのプロパティを定義するRole構造を単に返す必要があります。 この関数は、アリティ1のみをサポートします。

sequence機能を備えた作品は非常に興味深いものです。 ロールごとに一意の名前を生成する必要があります。 したがって、順次生成されます。 これを行うには、2つの引数を渡すsequence関数を使用します。1つ目はシーケンスを生成するフィールドの名前で、2つ目は文字列を返し、その中の値を補間する匿名関数です。 この関数を見てみましょう:

 &”Test Role #{&1}” 

Elixirに精通している場合は、匿名関数を記述する別の方法を学習している可能性があります。 これはおおよそ次のように変換されます。

 fn x -> "Test Role #{x}" end 

したがって、 sequence関数は次のように説明できます。

 sequence(:name, fn x -> "Test Role #{x}" end) 

最後に、管理フラグをfalseに設定しfalse 。 この値をデフォルト条件として使用します。 これを明示的に示すことにより、管理ロールを作成できます。 ExMachinaの他のより高度な機能については、少し後で説明します。 それでは、新しいRoleファクトリとコントローラーテストを組み合わせて時間をかけてみましょう。

コントローラテストにロールファクトリを追加する


最初にファイルtest/controllers/user_controller_test.exs開きます。 上部のsetupブロックで、新しいTestHelper.create_role関数の使用を追加します。

 # ... import Pxblog.Factory @valid_create_attrs %{email: "test@test.com", username: "test", password: "test", password_confirmation: "test"} @valid_attrs %{email: "test@test.com", username: "test"} @invalid_attrs %{} setup do user_role = insert(:role) {:ok, nonadmin_user} = TestHelper.create_user(user_role, %{email: "nonadmin@test.com", username: "nonadmin", password: "test", password_confirmation: "test"}) admin_role = insert(:role, admin: true) {:ok, admin_user} = TestHelper.create_user(admin_role, %{email: "admin@test.com", username: "admin", password: "test", password_confirmation: "test"}) {:ok, conn: build_conn(), admin_role: admin_role, user_role: user_role, nonadmin_user: nonadmin_user, admin_user: admin_user} end # ... 

ただし、その前に、ファクトリモジュール自体をインポートします。 10 行目で、 :roleファクトリを使用してロールを追加します。 13行目でも同じことを行いますが、adminフラグをtrueオーバーライドしtrue

ファイルを保存して、テストを再開します。 すべてがまだ合格しなければなりません! ここで、ユーザー用のファクトリを作成して、接続を作成します。

ユーザー用のファクトリーを追加する


ユーザー向けの工場をご覧ください。

 def user_factory do %User{ username: sequence(:username, &"User #{&1}"), email: "test@test.com", password: "test1234", password_confirmation: "test1234", password_digest: Comeonin.Bcrypt.hashpwsalt("test1234"), role: build(:role) } end 

基本的に、このファクトリは、ロールを作成するために以前に記述したものと一致します。 しかし、対処しなければならない落とし穴がいくつかあります。 上記の7行目でpassword_digest値をpassword_digestハッシュ値に設定していることがわかりpassword (ユーザーログインをシミュレートしているため、これも追加する必要があります)。 ComeoninからBcryptモジュールを呼び出し、hashpwsalt関数を使用して、 password / password_confirmationフィールドと同じ値を渡します。 次の行では、 roleを関連付けとして設定します。 build関数を使用して、アトムの形でアセンブルしたい関連付けの名前を渡します。

ユーザーファクトリを変更したら、ファイルtest/controllers/user_controller_test.exsに戻りましょう。

 setup do user_role = insert(:role) nonadmin_user = insert(:user, role: user_role) admin_role = insert(:role, admin: true) admin_user = insert(:user, role: admin_role) {:ok, conn: build_conn(), admin_role: admin_role, user_role: user_role, nonadmin_user: nonadmin_user, admin_user: admin_user} end 

最後に、 TestHelperへのすべての呼び出しをTestHelperへの呼び出しに置き換えます。 ロールを取得してファクトリーに転送し、正しいロールを持つユーザーを作成します。 その後、管理者と同じことを行いますが、テストを変更する必要はありません!

それらを実行し、それらがまだ緑色であることを確認します。 続けることができます。

投稿用の工場を追加する


私たちはすでに新しい工場を追加することに取り組んでいると思うので、後者の工場で作業することは問題を引き起こさないはずです。

ここには新しいものはないので、ファイルtest/controllers/post_controller_test.exs変更してみましょう。

 def post_factory do %Post{ title: "Some Post", body: "And the body of some post", user: build(:user) } end 

もう一度、 Pxblog.Factoryモジュールをimport 、呼び出しを行っているファクトリーの場所をテストで確認Pxblog.Factoryします。 次に、 setupブロックで投稿を作成するためのすべての手順をファクトリコールに置き換えます。 insert関数を使用して、 role構造が作成されます。この構造は、ファクトリを介してユーザーを作成するために使用され、最終的には、それに関連付けられた投稿を作成するために使用されます...

テストを実行します。 彼らは再び緑色になりました!

この場所から、他のすべてはただの余分な仕事です。 戻って、 TestHelperへのすべての呼び出しをFactory呼び出しに置き換えましょう。 これは特に新しいものでも刺激的なものでもないため、詳細の説明にはあまり注意を払いません。

工場を接続する他の方法


工場を各テストに明示的に接続するパスを選択しますが、同じことをしたくない場合は、次のいずれかの方法を使用できます。

ファイルtest/support/model_case.exusingブロックにエイリアスを追加します。

 using do quote do alias Pxblog.Repo import Ecto import Ecto.Changeset import Ecto.Query import Pxblog.ModelCase import Pxblog.Factory end end 

そして、ファイルtest/support/conn_case.ex

 using do quote do # Import conveniences for testing with connections use Phoenix.ConnTest alias Pxblog.Repo import Ecto import Ecto.Changeset import Ecto.Query import Pxblog.Router.Helpers import Pxblog.Factory # The default endpoint for testing @endpoint Pxblog.Endpoint end end 

ExMachinaのその他の機能


小さなブログエンジンの目的のために、ExMachinaが提供する他の機能は必要ありません。 たとえば、 buildcreateに加えて、利便性のためにいくつかの他の機能のサポートがありcreate (例としてbuildを使用buildていますが、これはcreateでも機能しcreate )。

 build_pair(:factory, attrs) <- Builds 2 models build_list(n, :factory, attrs) <- Builds N models 

buildメソッドをcreateしてcreateしたモデルを保存するには、 createメソッドを呼び出しcreate

 build(:role) |> insert 

その他の資料


ExMachinaの使用の詳細については、 Githubページをご覧ください 。 また、Thoughtbotの技術ブログにもアクセスできます。このブログでは、クリエイターがExMachina優れた発表やその他の使用方法を投稿しています。

まとめると


最初に、私は少し警戒心があり、以前ファクトリーガールの助けを借りていくつかのことを実装した方法を思い出しました。 ここですべてが同じになるのではないかと心配しました。 しかし、Elixirは私たちを自分自身から守ります。これは、テスト時にバランスを見つけるのに役立ちます。 構文は明確でクリーンです。 必要なコードの量が大幅に減少しました。 さらに非常に便利なライブラリを提供してくれた、Thoughtbotの輝かしいスタッフに感謝します。

Wunschからの結論


今日は非常に短い結論です。 エリクサーコミュニティに登録して、毎週ロシア語で興味深い記事を受け取ってください。

シリーズの他の記事


  1. エントリー
  2. ログイン
  3. 役割を追加
  4. コントローラーで役割を処理します
  5. ExMachinaを接続します
  6. マークダウンのサポート
  7. コメントを追加
  8. コメントで終了
  9. チャンネル
  10. チャネルテスト
  11. おわりに


研究の成功、私たちと一緒に!

Source: https://habr.com/ru/post/J316996/


All Articles