Testing در مسیر Elixir

یاد بگیرید چگونه تمرین‌های Elixir خود را در Exercism test کنید.


از ترمینال، به پوشه‌ی پایه‌ی تمرین بروید و سپس testها را با این دستور اجرا کنید:

$ mix test

این دستور، فایل test موجود در زیرپوشه‌ی test را اجرا می‌کند؛ یعنی فایلی که به _test.exs ختم می‌شود.

testهای در انتظار

در مجموعه‌ی testهای تمرین‌های عملی، همه‌ی testها به‌جز اولین test طوری برچسب خورده‌اند که نادیده گرفته شوند.

وقتی یک test را با موفقیت پاس کردید، می‌توانید test بعدی را با کامنت‌کردن @tag :pending مربوطه به کمک علامت # از حالت نادیده‌گرفته‌شده خارج کنید.

برای مثال:

# @tag :pending
test "shouting" do
  assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end

اگر می‌خواهید همه‌ی testها را یک‌جا اجرا کنید، می‌توانید با استفاده از پرچم --include در دستور mix test همه‌ی testهای نادیده‌گرفته‌شده را هم شامل کنید:

$ mix test --include pending

یا می‌توانید با کامنت‌کردن خط ExUnit.configure در مجموعه‌ی test، همه‌ی testها را فعال کنید.

# ExUnit.configure exclude: :pending, trace: true

امکانات تکمیلی test در Elixir

ExUnit و mix test روش‌های نسبتاً زیادی برای گروه‌بندی، برچسب‌گذاری و اجرای testها و همچنین روش‌های گوناگونی برای کنترل اجرای testها در اختیارتان می‌گذارند که خلاصه‌ی بیشترشان در ادامه آمده است.

روش‌هایی برای اجرای testهای مشخص

مستندات:

اجرای testها در یک فایل مشخص

همه‌ی testهای یک فایل واحد را می‌توان با mix test و با مشخص‌کردن فایل اجرا کرد:

$ mix test test/<FILE>.exs

نکته: tagging ممکن است بر اینکه با این روش واقعاً کدام testها اجرا می‌شوند تأثیر بگذارد.

اجرای testهای تکی

testهای تکی را می‌توان با ارجاع به شماره‌ی خط یک test در فایل اجرا کرد:

$ mix test test/<FILE>.exs:LINENUM

چند test را می‌توان با دادن چند شماره‌ی خط جدا شده با : اجرا کرد.

برای مثال، فایلی با محتوای زیر و شماره‌های خط را در نظر بگیرید:

test "Test 1" do           # 1
  # test implementation    # 2-6
end                        # 7
                           # 8
test "Test 2" do           # 9
  # test implementation    # 10-21
end                        # 22
                           # 23
test "Test 3" do           # 24
  # test implementation    # 25-35
end                        # 36

test اول و سوم را می‌توان این‌طور اجرا کرد:

$ mix test test/FILE.exs:1:24

نکته: وقتی testها را با شماره‌ی خط مشخص می‌کنید، tagging نادیده گرفته می‌شود.

اجرای گروه‌هایی از testها

testها را می‌توان با describe گروه‌بندی کرد:

describe "short test group description" do
  test "test description" do
    # test implementation
  end

  test "another test description" do
    # test implementation
  end
end

همه‌ی testهای یک گروه را می‌توان با ارجاع به شماره‌ی خط آن در فایل اجرا کرد، درست مانند ارجاع به testهای تکی و اجرای آن‌ها.

مستندات:

سایر گزینه‌های مفید mix test

  • --include و --exclude: بر اساس @tagهای هر test، testهای مشخصی را اجرا می‌کند یا اجرا نمی‌کند
  • --failed: فقط testهایی را اجرا می‌کند که در آخرین اجرا شکست خورده بودند
  • --max-failures: وقتی تعداد شکست‌های test به این عدد برسد، مجموعه اجرای testها را متوقف می‌کند
  • --seed: مولد اعداد تصادفی را که برای درهم‌ریختن ترتیب testها به کار می‌رود مقداردهی می‌کند. --seed 0 تصادفی‌سازی را غیرفعال می‌کند تا testهای یک فایل همیشه به همان ترتیبی که تعریف شده‌اند اجرا شوند
  • --stale: فقط testهایی را اجرا می‌کند که به ماژول‌هایی ارجاع می‌دهند که از آخرین باری که testها با --stale اجرا شده‌اند تغییر کرده‌اند
  • --only task_id:1: یا با عددی دیگر؛ در تمرین‌های مفهومی فقط testهای مربوط به وظیفه‌ی مشخص را اجرا می‌کند

مستندات:

Typespecs و Dialyzer (DIscrepancy AnalYZer for ERlang programs)

تمرین‌های Elixir شامل یک فایل پیاده‌سازی اسکلتی در زیرپوشه‌ی lib هستند. این فایل، ماژول و توابعی را که انتظار می‌رود پیاده‌سازی کنید مشخص می‌کند. در بیشتر تمرین‌ها، بالای تعریف تابع typespecهایی می‌بینید. این‌ها با تگ @spec شروع می‌شوند و معمولاً قالب @spec function_name(type1, type2) :: return_type را دنبال می‌کنند. این‌ها در Elixir و Erlang به‌عنوان مستندات و در کنار ابزاری به نام Dialyzer برای یافتن ناسازگاری‌های نوع و باگ‌های احتمالی به کار می‌روند. برای اطلاعات بیشتر مستندات typespec را ببینید. برای مستندات مربوط به Dialyzer نیز Erlang -- dialyzer را ببینید.

به‌صورت اختیاری، ممکن است بخواهید نوع‌های پیاده‌سازی خود را با Dialyzer بررسی کنید. برای این کار باید چند قدم بردارید. برای انجام این کار، باید وابستگی Dialyxir را به فایل mix.exs تمرین خود اضافه کنید.

defp deps do
  # Add this:
  [{:dialyxir, "~> 0.4", only: [:dev]}]
end

سپس از mix taskها برای دریافت و کامپایل از خط فرمان استفاده کنید:

$ mix deps.get
...
$ mix deps.compile
...

اگر اولین بار است که Dialyzer را اجرا می‌کنید، به احتمال زیاد فایل plt را ندارید. جدول جست‌وجوی پایدار، یا PLT، توسط Dialyzer برای ذخیره‌ی اطلاعات مربوط به نوع‌های توکار Elixir و Erlang به کار می‌رود. برای ساختن یک PLT با پیش‌فرض‌های معقول، این دستور را اجرا کنید:

$ mix dialyzer --plt

و در نهایت، می‌توان آن را این‌طور اجرا کرد:

$ mix dialyzer

مطمئن شوید که مسیر را به مسیر کتابخانه‌های Elixir در سیستم خودتان تغییر دهید. برای مثال، اگر Elixir را با homebrew نصب کرده باشید، احتمالاً آن را زیر /usr/local/Cellar/elixir/1.3.2 پیدا می‌کنید.

باید تأکید کرد که اجرای Dialyzer و حذف همه‌ی هشدارها هنگام حل یک تمرین، مرحله‌ای اختیاری است. ممکن است رمزگشایی هشدارهای Dialyzer دشوار باشد. برای مثال، هشدارهای این پیاده‌سازی بسیار مسخره از تمرین Bob را بررسی کنید.

defmodule Bob do
  @spec hey(input :: String.t()) :: String.t()
  def hey(input) do
    1
  end

  def hey(input) do
  end
end

این کد هشدارهای زیر را تولید می‌کند.

bob.exs:2: Invalid type specification for function 'Elixir.Bob':hey/1. The success typing is (_) -> 1
bob.exs:7: The variable _input@1 can never match since previous clauses completely covered the type any()

هشدار اول یعنی اینکه تابع نوع درست را برنمی‌گرداند. هشدار آخر نشان می‌دهد که هرگز به تعریف دوم تابع نمی‌رسیم، چون تعریف اول تابع همیشه تطبیق پیدا می‌کند.