আপনি কি আপনার রুবি অ্যাপ্লিকেশনের জন্য RSpec ব্যবহার করে টেস্ট লিখতে শিখতে চান?
তাহলে আপনি সঠিক জায়গায় আছেন!
এই টিউটোরিয়ালে আমি আপনাকে দেখাব কীভাবে করবেন।
সামগ্রী
- ১ কেন আপনার টেস্ট লিখা উচিত?
- ১.০.১ এটি ত্রুটির বিপরীতে একটি সেফটি নেট তৈরি করে (রিফ্যাক্টরিং-এর জন্য বিশেষত উপকারী)
- ১.০.২ এটি আপনার কোড ডকুমেন্ট করতে সাহায্য করে
- ১.০.৩ এটি আপনাকে একটি ফিডব্যাক লুপ দেয়
- ১.০.৪ এটি নিশ্চিত করতে সাহায্য করে যে আপনার কোড আপনার প্রত্যাশা অনুযায়ী ফলাফল দিচ্ছে
- ১.০.৫ এটি আপনাকে একটি রুবি জব পাওয়াতে সাহায্য করে
- ২ RSpec-এর সাথে শুরু করা
- ৩ RSpec টেস্টিং উদাহরণ
- ৪ RSpec Let মেথড
- ৫ Subject মেথড কীভাবে ব্যবহার করবেন
- ৬ সব টেস্টের আগে কোড চালানোর পদ্ধতি
- ৭ টেস্টিং সাবগ্রুপ কীভাবে তৈরি করবেন
- ৮ একটি টেস্ট অস্থায়ীভাবে ডিজেবল করার পদ্ধতি
- ৯ নাম দিয়ে উদাহরণ চালানো
- ১০ RSpec এক্সপেকটেশন এবং ম্যাচার
- ১১ RSpec ফরম্যাটার
- ১২ স্লো টেস্ট খুঁজে বের করার পদ্ধতি
- ১৩ RSpec ভিডিও টিউটোরিয়াল
- ১৪ সারসংক্ষেপ
- ১৪.১ সম্পর্কিত
কেন আপনার টেস্ট লিখা উচিত?
কারণগুলো নিচে:
এটি ত্রুটির বিপরীতে একটি সেফটি নেট তৈরি করে (রিফ্যাক্টরিং-এর জন্য বিশেষত উপকারী)
আপনার যদি টেস্ট সিউট না থাকে তবে আপনি আপনার কোড স্পর্শ করতে চাবেন না, কিছু ভাঙা যেতে পারে এর ভয়ে… টেস্ট থাকলে আপনার আত্মবিশ্বাস বেড়ে!
এটি আপনার কোড ডকুমেন্ট করতে সাহায্য করে
আপনার টেস্টগুলো বর্ণনা করে আপনার অ্যাপ্লিকেশন কী করতে হবে।
এটি আপনাকে একটি ফিডব্যাক লুপ দেয়
আপনি যখন TDD করছেন আপনি একটি ফিডব্যাক লুপ পান যা আপনাকে বলে পরবর্তীতে কীতে ফোকাস করবেন, আপনি সহজে ভटकলে উপকারী।
এটি নিশ্চিত করতে সাহায্য করে যে আপনার কোড আপনার প্রত্যাশা অনুযায়ী ফলাফল দিচ্ছে
এটি খুব গুরুত্বপূর্ণ! আপনি যদি কিছু জটিল লজিক লিখছেন, তবে আপনি নিশ্চিত হতে চান এটি অনেক ভিন্ন ইনপুটের সাথে কাজ করছে শুধু একটি উদাহরণ দিয়ে নয়। টেস্টগুলো আপনাকে কনার কেসগুলো খুঁজে বের করতে এবং ডকুমেন্ট করতে সাহায্য করে।
এটি আপনাকে একটি রুবি জব পাওয়াতে সাহায্য করে
অধিকাংশ জব অ্যাপ্লিকেশন আপনার টেস্টিং স্কিলকে যাগবে, আপনার জব পাওয়ার চান্স বাড়িয়ে দেবে।
RSpec-এর সাথে শুরু করা
RSpec কীভাবে কাজ করে বুঝতে আসুন একটি উদাহরণ ধাপে ধাপে যেতে দিয়ে।
আমরা একটি সিম্পল অ্যাপ্লিকেশন লিখব যা ফ্যাক্টোরিয়াল নম্বর খুঁজে বের করে।
প্রথম ধাপ:
require 'rspec/autorun' describe Factorial do # ... end
এটি আপনার প্রথম RSpec টেস্ট লিখার প্রাথমিক কোড। আপনাকে rspec জেম রিকোয়ার করতে হবে। তারপর একটি describe ব্লক তৈরি করতে হবে সব টেস্ট একসাথে গ্রুপ করার জন্য এবং RSpec কে বলতে হবে আপনি কোন ক্লাস টেস্ট করছেন।
পরবর্তী হলো it ব্লক:
describe Factorial do
it "does something" do
# ...
end
end
এটি টেস্টের নাম, প্লাস টেস্টের সব কম্পোনেন্ট একসাথে গ্রুপ করার একটি পদ্ধতি। কম্পোনেন্টগুলো হলো:
- সেটআপ
- এক্সারসাইজ
- ভারিফাই
সেটআপ হলো যেখানে আপনি প্রয়োজনীয় অবজেক্টগুলো তৈরি করেন। এটি প্রস্তুতির ফেজ। তারপর আপনি যে মেথডটি এক্সারসাইজ করতে চান সেটা কল করেন এর রিটার্ন ভ্যালু পেতে। শেষে, আপনি এক্সপেকটেশন (RSpec) বা অ্যাসারশন (Minitest) দিয়ে ফলাফল ভেরিফাই করেন।
RSpec টেস্টিং উদাহরণ
এখন যদি আমরা একটি ফ্যাক্টোরিয়াল মেথড লিখতে চাই, তবে আমাদের কিছু বৈধ ভ্যালু অনলাইন বা হ্যান্ড ক্যালকুলেশন দিয়ে খুঁজে বের করতে হবে। তারপর আমরা সেগুলো আমাদের টেস্টের সাথে ব্যবহার করব।
এভাবে:
describe Factorial do
it "finds the factorial of 5" do
calculator = Factorial.new
expect(calculator.factorial_of(5)).to eq(120)
end
end
আপনি যখন এই কোডটি রান করবেন (সাধারণ রুবি প্রোগ্রামের মতো) তবে আপনি পাবেন:
uninitialized constant Factorial (NameError)
এটি স্বাভাবিক কারণ আমাদের এখনো Factorial ক্লাস নেই। আসুন একটি তৈরি করি:
class Factorial end
পরবর্তী এরর হবে:
undefined method 'factorial_of'
আমি factorial_of মেথড তৈরি করে এটাকে ফিক্স করি:
class Factorial def factorial_of end end
তারপর আবার কোডটি চালান:
wrong number of arguments (given 1, expected 0)
আরেকটি এরর! কিন্তু জানেন কী? এটি একটি ভালো জিনিস 🙂 এরর কিছু হতাশ होने वाली জিনিস নয়। এগুলো ফিডব্যাক। এখন: factorial_of মেথডে একটি আর্গুমেন্ট যোগ করুন:
class Factorial def factorial_of(n) end end
এখন আপনি পাবেন একটি টেস্ট ফেইলিয়ার:
expected: 120 got: nil
এটি সঠিকভাবে সেটি পয়েন্ট যেখানে আপনি এই মুহূর্তে থাকতে চান! পরবর্তী টাস্ক হলো মেথডটি ইমপ্লিমেন্ট করা:
class Factorial
def factorial_of(n)
(1..n).inject(:*)
end
end
এবং আপনি পাবেন আপনার প্রথম পাসিং টেস্ট:
. Finished in 0.00315 seconds (files took 0.09083 seconds to load) 1 example, 0 failures
এটিই আমরা টেস্ট-ড্রাইভেন ডেভেলপমেন্ট (TDD) বলি। আপনি প্রথমে টেস্ট লিখেন, তারপর টেস্টগুলো আপনাকে গাইড করে আপনাকে কী করতে হবে সেটা বুঝাতে।
RSpec Let মেথড
আপনি যদি অনেক টেস্ট লিখতে চান এবং একই অবজেক্টগুলো পুনরাবৃত্তি ব্যবহার করতে চান তবে আপনি এই অবজেক্টগুলো let স্টেটমেন্ট দিয়ে ডিফাইন করতে পারেন। এটি এমন দেখয়:
describe Factorial do
let(:calculator) { Factorial.new }
it "finds the factorial of 5" do
expect(calculator.factorial_of(5)).to eq(120)
end
end
এখন আপনি একই describe ব্লকের অধীনে সব টেস্টে calculator পুনরাবৃত্তি ব্যবহার করতে পারেন। let-এর সম্পর্কে একটি জিনিস জানা দরকার এটি "লেজি"। এর মানে কী? অবজেক্টটি প্রথমবার আপনি এটি ব্যবহার করার সময় তৈরি হবে। এটার ফরক পড়তে পারে যদি এই অবজেক্ট তৈরি করার সাইড-ইফেক্ট থাকে, যেমন ডেটাবেস এন্ট্রি তৈরি করা, বা ফাইলে লিখা। সাইড-ইফেক্ট এড়াতে ভালো, কিন্তু আপনি যদি না পারেন তবে let! মেথড ব্যবহার করুন। উদাহরণ:
let!(:user) { User.create("rspec@rubyguides.com") }
let! মেথড নন-লেজি, তাই অবজেক্টটি যেকোনো টেস্ট চালু হওয়ার আগে তৈরি হয়ে যাবে।
Subject মেথড কীভাবে ব্যবহার করবেন
let-এর আরেকটি ভার্সন হলো subject। একমাত্র পার্থক্য হলো আপনার শুধু একটি subject থাকতে পারে, এবং এটি মূল অবজেক্টের একটি ইনস্ট্যান্স হওয়া উচিত যেটি আপনি টেস্ট করছেন। RSpec ইতিমধ্যে একটি ডিফল্ট subject তৈরি করে এমনভাবে:
subject { Factorial.new }
এটিকে "ইম্প্লিসিট সাবজেক্ট" বলা হয়। আপনি এটাকে এভাবে ব্যবহার করতে পারেন:
describe Factorial do
it "finds the factorial of 5" do
expect(subject.factorial_of(5)).to eq(120)
end
end
আপনি আপনার সাবজেক্টকে একটি নাম দিতে পারেন:
subject(:calculator) { Factorial.new }
এটি let ব্যবহার করার মতোই আচরণ করে, কিন্তু এটি এক-লাইন এক্সপেকটেশন সক্ষম করে:
it { should be_empty }
সব টেস্টের আগে কোড চালানোর পদ্ধতি
RSpec-এ এক্সিকিউশন হুক রয়েছে যা আপনি ব্যবহার করতে পারেন প্রতিটি টেস্টের আগে ও পরে, বা পুরো গ্রুপের জন্য কিছু চালানোর জন্য। উদাহরণস্বরূপ:
describe Shop do
before(:all) { Shop.prepare_database }
after (:all) { Shop.cleanup_database }
end
আপনি যদি প্রতিটি উদাহরণের জন্য (RSpec-এ উদাহরণ = টেস্ট) এই কোড চালাতে চান তবে :each ব্যবহার করুন :all-এর বদলে।
টেস্টিং সাবগ্রুপ কীভাবে তৈরি করবেন
আপনি যদি আপনার অ্যাপে ভিন্ন সিনেরিও টেস্ট করেন তবে রিলেটেড টেস্টগুলো একসাথে গ্রুপ করা সহায়ক হতে পারে। আপনি RSpec-এ context ব্লক ব্যবহার করে এটি করতে পারেন। এখানে একটি উদাহরণ:
describe Course do
context "when user is logged in" do
it "displays the course lessons" do
end
it "displays the course description" do
end
end
context "when user it NOT logged in" do
it "redirects to login page" do
end
it "it shows a message" do
end
end
end
একটি টেস্ট অস্থায়ীভাবে ডিজেবল করার পদ্ধতি
ডিবাগিং উদ্দেশ্যে একটি টেস্ট ডিজেবল করা সম্ভব। আপনাকে শুধু it-কে xit-এ পরিবর্তন করতে হবে সেই টেস্টগুলোর জন্য যা আপনি ডিজেবল করতে চান। উদাহরণ:
xit "eats lots of bacon" do end
খেলা শেষ হলে x সরিয়ে ফেলা ভুলবেন না!
নাম দিয়ে উদাহরণ চালানো
টেস্ট ডিজেবল করার বদলে, আপনি -e ফ্ল্যাগ দিয়ে আপনি যে টেস্টগুলো চালাতে চান সেগুলো ফিল্টার করতে পারেন। উদাহরণ:
> ruby person.rb -e bacon
এই ফিল্টারিং টেস্টের নামের ওপর ভিত্তি করে, তাই উপরের উদাহরণটি "bacon" শব্দ থাকা যেকোনো টেস্টকে ম্যাচ করবে।
RSpec এক্সপেকটেশন এবং ম্যাচার
আপনি সاید আমরা যে উদাহরণটি ব্যবহার করছি সেটি মনে আছে:
expect(calculator.factorial_of(5)).to eq(120)
কিন্তু এই eq(120) পার্টটি কী? ১২০ হলো আমরা যে ভ্যালু এক্সপেক্ট করছি… এবং eq হলো আমরা যা একটি ম্যাচার বলি। ম্যাচারগুলো হলো RSpec কীভাবে আপনার মেথডের আউটপুট আপনার এক্সপেক্টেড ভ্যালু-এর সাথে কমপেয়ার করে। eq-এর ক্ষেত্রে, RSpec == অপারেটর ব্যবহার করে (রুবি অপারেটর সম্পর্কে আরও পড়ুন)। কিন্তু অন্যান্য ম্যাচারও রয়েছে যা আপনি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, be_something ম্যাচার:
expect(nil).to be_nil
যেখানে something হলো একটি প্রিডিকেট মেথড (যেমন empty?) যা টেস্ট রেজাল্টের ওপর কল হবে। অন্যান্য উপকারী ম্যাচার:
- include (অ্যারে ও হ্যাশের জন্য)
- start_with
- end_with
- match (রেগুলার এক্সপ্রেশন ম্যাচিং জন্য)
- be_between
- have_key / have_value (হ্যাশের জন্য)
- be_instance_of
- respond_to
- have_attributes (ইনস্ট্যান্স ভেরিয়েবল টেস্ট করার জন্য)
একটি ম্যাচার যেটির বিশেষ মনোযোগ দরকার সেটি raise_error ম্যাচার। কারণ এটি ব্যবহার করতে আপনাকে আপনার এক্সপেকটেশনকে একটি ব্লকে র্যাপ করতে হয়। এভাবে:
expect{ :x.count }.to raise_error(NoMethodError)
change ম্যাচারও এভাবে কাজ করে:
expect{ stock.increment }.to change(stock, :value).by(100)
RSpec ফরম্যাটার
ডিফল্ট RSpec আউটপুট "প্রগ্রেস" ফরম্যাটে থাকে। এই ফরম্যাটে আপনি ডট (.) দেখবেন প্রতিটি পাসিং টেস্টকে প্রতীক করে, F ফেইলড টেস্টের জন্য (এক্সপেক্টেড ও একচুয়াল ম্যাচ করে না), বা E এরর জন্য। কিন্তু অল্টার্নেটিভ ফরম্যাটিং অপশনও রয়েছে। এখানে একটি তালিকা:
- progress
- documentation
- json
- html
আপনি -f ফ্ল্যাগ দিয়ে এনেবল করতে পারেন:
> ruby factorial.rb -f d Person eats lots of healthy food writes many articles Finished in 0.00154 seconds (files took 0.09898 seconds to load) 2 examples, 0 failures
ডকুমেন্টেশন ফরম্যাট আপনার টেস্ট ডেসক্রিপশন ব্যবহার করে আউটপুট জেনারেট করে।
স্লো টেস্ট খুঁজে বের করার পদ্ধতি
RSpec-এ একটি খুব হ্যান্ডি অপশন রয়েছে আপনার টেস্টগুলো প্রোফাইল করার জন্য। শুধু --profile ফ্ল্যাগ পাস করলে আপনি দেখতে পাবেন প্রতিটি টেস্ট কতক্ষণ লাগছে এবং খুব স্লোগুলো ফিক্স করতে পারবেন। এখানে একটি উদাহরণ:
> ruby factorial.rb --profile Factorial finds the factorial of 5 0.00043 seconds
RSpec ভিডিও টিউটোরিয়াল
সারসংক্ষেপ
আপনি RSpec টেস্টিং ফ্রেমওয়ার্ক ব্যবহার করে টেস্ট লিখা শিখলেন। এখন আপনার পালা আপনার নিজস্ব টেস্ট লিখা শুরু করার! পড়ার জন্য ধন্যবাদ!