Elixir ট্র্যাকে টেস্টিং

Exercism-এ আপনার Elixir অনুশীলনীগুলো টেস্ট করা শিখুন


টার্মিনাল থেকে অনুশীলনীর বেস ডিরেক্টরিতে যান, তারপর এই কমান্ড দিয়ে টেস্ট চালান:

$ mix test

এটি test সাবফোল্ডারে থাকা টেস্ট ফাইলটি চালাবে, অর্থাৎ _test.exs দিয়ে শেষ হওয়া ফাইলটি।

পেন্ডিং টেস্ট

প্র্যাকটিস অনুশীলনীর টেস্ট স্যুটে প্রথম টেস্টটি ছাড়া বাকি সবগুলো স্কিপ করার জন্য ট্যাগ করা থাকে।

একটি টেস্ট পাস হয়ে গেলে, # চিহ্ন দিয়ে সংশ্লিষ্ট @tag :pending কমেন্ট আউট করে পরের টেস্টটি আনস্কিপ করতে পারেন।

উদাহরণস্বরূপ:

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

একসাথে সব টেস্ট চালাতে চাইলে, mix test কমান্ডে --include ফ্ল্যাগ ব্যবহার করে স্কিপ করা সব টেস্ট অন্তর্ভুক্ত করতে পারেন:

$ mix test --include pending

অথবা, টেস্ট স্যুটের ExUnit.configure লাইনটি কমেন্ট আউট করে সব টেস্ট চালু করতে পারেন।

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

Elixir টেস্টিংয়ের আরও কিছু ফিচার

ExUnit ও mix test টেস্ট গ্রুপ করা, ট্যাগ করা ও চালানোর বেশ কিছু উপায় এবং টেস্ট চালানো নিয়ন্ত্রণের নানা পদ্ধতি দেয়, যার অনেকটাই নিচে সংক্ষেপে দেওয়া হলো।

নির্দিষ্ট টেস্ট চালানোর পদ্ধতি

ডকুমেন্টেশন:

নির্দিষ্ট একটি ফাইলের টেস্ট চালানো

ফাইলটি উল্লেখ করে mix test দিয়ে একটি ফাইলের সব টেস্ট চালানো যায়:

$ mix test test/<FILE>.exs

দ্রষ্টব্য: tagging-এর কারণে এই পদ্ধতিতে আসলে কোন টেস্টগুলো চালানো হবে তা প্রভাবিত হতে পারে।

একক টেস্ট চালানো

ফাইলে একটি টেস্টের লাইন নম্বর উল্লেখ করে একক টেস্ট চালানো যায়:

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

: দিয়ে আলাদা করা একাধিক লাইন নম্বর দিয়ে একাধিক টেস্ট চালানো যায়।

উদাহরণস্বরূপ, লাইন নম্বরসহ নিচের বিষয়বস্তুওয়ালা একটি ফাইল ধরা যাক:

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

১ম ও ৩য় টেস্ট এভাবে চালানো যায়:

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

দ্রষ্টব্য: লাইন নম্বর দিয়ে টেস্ট নির্দিষ্ট করলে tagging উপেক্ষা করা হয়।

টেস্টের গ্রুপ চালানো

describe দিয়ে টেস্ট গ্রুপ করা যায়:

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

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

একক টেস্ট উল্লেখ ও চালানোর মতোই, ফাইলে একটি গ্রুপের লাইন নম্বর উল্লেখ করে গ্রুপের সব টেস্ট চালানো যায়।

ডকুমেন্টেশন:

mix test-এর আরও কিছু দরকারি অপশন

  • --include ও --exclude - @tag-এর ভিত্তিতে নির্দিষ্ট টেস্ট চালায় বা চালায় না
  • --failed - শুধু সেই টেস্টগুলো চালায় যেগুলো গতবার চালানোর সময় ফেল করেছিল
  • --max-failures - এই সংখ্যক টেস্ট ফেল হলে স্যুটটি আর টেস্ট মূল্যায়ন করা বন্ধ করে দেয়
  • --seed - টেস্টের ক্রম র‍্যান্ডম করতে ব্যবহৃত র‍্যান্ডম নম্বর জেনারেটরে সিড দেয় --seed 0 র‍্যান্ডমাইজেশন বন্ধ করে দেয়, ফলে একটি ফাইলের টেস্টগুলো সবসময় যেই ক্রমে ডিফাইন করা হয়েছিল সেই ক্রমেই চলবে
  • --stale - শুধু সেই টেস্টগুলো চালায় যেগুলো এমন মডিউল উল্লেখ করে, যা শেষবার --stale দিয়ে টেস্ট চালানোর পর থেকে বদলে গেছে
  • --only task_id:1 - অথবা অন্য কোনো নম্বর দিয়ে, লার্নিং অনুশীলনীতে শুধু নির্দিষ্ট টাস্কের সাথে সম্পর্কিত টেস্টগুলো চালায়

ডকুমেন্টেশন:

টাইপস্পেক ও Dialyzer (DIscrepancy AnalYZer for ERlang programs)

Elixir অনুশীলনীতে lib সাবডিরেক্টরিতে একটি স্কেলিটন ইমপ্লিমেন্টেশন ফাইল থাকে। এই ফাইলে আপনার যে মডিউল ও ফাংশনগুলো ইমপ্লিমেন্ট করার কথা, সেগুলোর রূপরেখা দেওয়া থাকে। বেশিরভাগ অনুশীলনীতে ফাংশন ডিক্লারেশনের উপরে টাইপস্পেক পাবেন। এগুলো @spec ট্যাগ দিয়ে শুরু হয় এবং সাধারণত @spec function_name(type1, type2) :: return_type ফরম্যাট অনুসরণ করে। Elixir ও Erlang-এ এগুলো ডকুমেন্টেশন হিসেবে এবং টাইপের অসঙ্গতি ও সম্ভাব্য বাগ খুঁজে বের করতে Dialyzer নামের একটি টুলের সাথে মিলিয়ে ব্যবহার করা হয়। আরও তথ্যের জন্য টাইপস্পেক ডকুমেন্টেশন দেখুন। Dialyzer-এর ডকুমেন্টেশনের জন্য দেখুন Erlang -- dialyzer।

চাইলে আপনি Dialyzer দিয়ে আপনার ইমপ্লিমেন্টেশনের টাইপ যাচাই করতে পারেন। এর জন্য আপনাকে কয়েকটি ধাপ নিতে হবে। সেটা করতে হলে, আপনার সমস্যার mix.exs ফাইলে Dialyxir ডিপেন্ডেন্সি যোগ করতে হবে।

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

তারপর কমান্ড লাইন থেকে mix টাস্ক ব্যবহার করে ডিপেন্ডেন্সি নামিয়ে কম্পাইল করুন:

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

আপনি যদি প্রথমবার Dialyzer চালান, তাহলে সম্ভবত আপনার কাছে plt ফাইল থাকবে না। বিল্ট-ইন Elixir ও Erlang টাইপ সম্পর্কিত তথ্য ক্যাশ করতে Dialyzer যে টেবিলটি ব্যবহার করে তার নাম Persistent Lookup Table বা PLT (অর্থাৎ স্থায়ী লুকআপ টেবিল)। যুক্তিসঙ্গত ডিফল্ট মানসহ একটি plt তৈরি করতে চালান:

$ mix dialyzer --plt

সবশেষে, এটি এভাবে চালানো যায়:

$ mix dialyzer

Elixir লাইব্রেরিগুলোর জন্য আপনার সিস্টেমে যে পাথ আছে, সেখানে পাথটি বদলে নিতে ভুলবেন না। উদাহরণস্বরূপ, আপনি যদি homebrew দিয়ে Elixir ইনস্টল করে থাকেন, তাহলে সম্ভবত সেটি /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()

প্রথম ওয়ার্নিংটির অর্থ হলো ফাংশনটি সঠিক টাইপ রিটার্ন করছে না। শেষটি বোঝায় যে দ্বিতীয় ফাংশন ডেফিনিশন কখনোই পৌঁছানো যাবে না, কারণ প্রথম ফাংশন ডেফিনিশনটি সবসময় মিলে যায়।