এটা আমাদের সবার ক্ষেত্রে ঘটছে. সফ্টওয়্যার প্রকল্পগুলি বাড়ার সাথে সাথে, কোডবেসের অংশগুলি একটি ব্যাপক পরীক্ষা স্যুট ছাড়াই উত্পাদনে শেষ হয়। আপনি যখন কয়েক মাস পর কোডের একই এলাকায় আরেকবার দেখেন, তখন বুঝতে অসুবিধা হতে পারে; আরও খারাপ, একটি বাগ থাকতে পারে, এবং আমরা জানি না কোথায় এটি ঠিক করা শুরু করব৷
৷পরীক্ষা ছাড়া কোড পরিবর্তন করা একটি বড় চ্যালেঞ্জ। আমরা নিশ্চিত হতে পারি না যে আমরা প্রক্রিয়ায় কিছু ভাঙব কিনা, এবং ম্যানুয়ালি সবকিছু পরীক্ষা করা, সর্বোত্তমভাবে, ভুলের প্রবণতা; সাধারণত, এটা অসম্ভব।
এই ধরনের কোডের সাথে মোকাবিলা করা হল ডেভেলপার হিসাবে আমরা যে কাজগুলি করি তার মধ্যে একটি সবচেয়ে সাধারণ কাজ, এবং অনেক কৌশল এই সমস্যাটির উপর কয়েক বছর ধরে ফোকাস করেছে, যেমন ক্যারেক্টারাইজেশন টেস্ট, যা আমরা আগের একটি প্রবন্ধে আলোচনা করেছি৷
আজ, আমরা ক্যারেক্টারাইজেশন টেস্টের উপর ভিত্তি করে আরেকটি কৌশল কভার করব এবং কেন্ট বেক দ্বারা প্রবর্তন করা হয়েছে, যিনি বহু বছর আগে আধুনিক প্রোগ্রামিং জগতে TDD-এর সাথে পরিচয় করিয়ে দিয়েছিলেন।
টিসিআর কি?
TCR মানে "টেস্ট, কমিট, রিভার্ট" কিন্তু এটাকে "টেস্ট &&কমিট || রিভার্ট" বলাটা আরও সঠিক। দেখা যাক কেন।
এই কৌশলটি লিগ্যাসি কোড পরীক্ষা করার জন্য একটি ওয়ার্কফ্লো বর্ণনা করে। আমরা একটি স্ক্রিপ্ট ব্যবহার করব যা প্রতিবার আমাদের প্রকল্প ফাইলগুলি সংরক্ষণ করার সময় পরীক্ষা চালাবে। প্রক্রিয়াটি নিম্নরূপ:
- প্রথমে, আমরা লিগ্যাসি কোডের যে অংশটি পরীক্ষা করতে চাই তার জন্য আমরা একটি খালি ইউনিট পরীক্ষা তৈরি করি।
- তারপর আমরা একটি একক দাবি যোগ করি এবং পরীক্ষা সংরক্ষণ করি।
- যেহেতু আমরা আমাদের স্ক্রিপ্ট সেট আপ করেছি, পরীক্ষাটি স্বয়ংক্রিয়ভাবে চালানো হয়। এটি সফল হলে, পরিবর্তন প্রতিশ্রুতিবদ্ধ। যদি এটি ব্যর্থ হয়, পরিবর্তনটি মুছে ফেলা হয় (প্রত্যাবর্তন করা হয়), এবং আমাদের আবার চেষ্টা করতে হবে।
একবার পরীক্ষা পাস হয়ে গেলে, আমরা তারপরে একটি নতুন টেস্ট কেস যোগ করতে পারি।
মূলত, টিসিআর হল আপনার কোডকে "সবুজ" অবস্থায় রাখার পরিবর্তে একটি ব্যর্থ পরীক্ষা প্রথমে (লাল) লেখার এবং তারপরে এটিকে পাস (সবুজ) করা, যেমনটি আমরা পরীক্ষা-চালিত বিকাশের সাথে করি। যদি আমরা একটি ব্যর্থ পরীক্ষা লিখি, এটি কেবল অদৃশ্য হয়ে যাবে, এবং আমাদের আবার "সবুজ" অবস্থায় ফিরিয়ে আনা হবে৷
উদ্দেশ্য
এই কৌশলটির মূল লক্ষ্য হল প্রতিবার যখন আপনি একটি টেস্ট কেস যোগ করবেন তখন কোডটি একটু ভালোভাবে বোঝা। এটি স্বাভাবিকভাবেই পরীক্ষার কভারেজ বাড়াবে এবং অনেক রিফ্যাক্টরিং আনব্লক করবে যা অন্যথায় সম্ভব হবে না।
TCR এর একটি সুবিধা হল যে এটি অনেক পরিস্থিতিতে কার্যকর। আমরা এটি এমন কোডের সাথে ব্যবহার করতে পারি যার কোনো পরীক্ষা নেই বা আংশিকভাবে পরীক্ষিত কোডের সাথে। পরীক্ষায় উত্তীর্ণ না হলে, আমরা শুধু পরিবর্তনটি প্রত্যাবর্তন করে আবার চেষ্টা করি।
আমরা কিভাবে এটি ব্যবহার করতে পারি?
কেন্ট বেক বিভিন্ন নিবন্ধ এবং ভিডিওতে (শেষে লিঙ্ক করা) দেখায় যে একটি ভাল পদ্ধতি হল একটি স্ক্রিপ্ট ব্যবহার করা যা প্রকল্পের নির্দিষ্ট ফাইলগুলি সংরক্ষণ করার পরে চলে।
আপনি যে প্রকল্পটি পরীক্ষা করার চেষ্টা করছেন তার উপর এটি ব্যাপকভাবে নির্ভর করবে। নিম্নলিখিত স্ক্রিপ্টের মতো কিছু, যা প্রতিবার সম্পাদন করা হয় যখন আমরা সম্পাদকে একটি প্লাগইন দিয়ে ফাইল সংরক্ষণ করি, এটি একটি ভাল শুরু:
(rspec && git commit -am "WIP") || git reset --hard
আপনি যদি ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করেন তবে প্রতিটি সংরক্ষণে চালানোর জন্য একটি ভাল প্লাগইন হল "রাননসেভ"। আপনি আপনার প্রকল্পের জন্য উপরের কমান্ড বা অনুরূপ একটি অন্তর্ভুক্ত করতে পারেন। এই ক্ষেত্রে, সম্পূর্ণ কনফিগার ফাইল হবে
{
"folders": [{ "path": "." }],
"settings": {
"emeraldwalk.runonsave": {
"commands": [
{
"match": "*.rb",
"cmd": "cd ${workspaceRoot} && rspec && git commit -am WIP || git reset --hard"
}
]
}
}
}
মনে রাখবেন যে পরে, আপনি কমান্ড লাইনে সরাসরি গিটের সাথে কমিট স্কোয়াশ করতে পারেন বা আপনি যদি গিথুব ব্যবহার করেন তবে পিআর মার্জ করার সময়:
।
এর মানে আমরা যে শাখায় কাজ করছি সেই শাখায় আমরা যে সমস্ত কমিট করেছি তার জন্য আমরা প্রধান শাখায় শুধুমাত্র একটি কমিট পাব। Github থেকে এই চিত্রটি এটি ভালভাবে ব্যাখ্যা করে:
।
টিসিআর দিয়ে আমাদের প্রথম পরীক্ষা লিখছি
কৌশলটি ব্যাখ্যা করার জন্য আমরা একটি সহজ উদাহরণ ব্যবহার করব। আমাদের একটি ক্লাস আছে যা আমরা জানি যে কাজ করছে, কিন্তু আমাদের এটি সংশোধন করতে হবে৷
আমরা শুধু একটি পরিবর্তন করতে পারি এবং পরিবর্তনগুলি স্থাপন করতে পারি। যাইহোক, আমরা নিশ্চিত হতে চাই যে আমরা প্রক্রিয়ার মধ্যে কোনো কিছু ভাঙব না, যা সর্বদা একটি ভাল ধারণা।
# worker.rb
class Worker
def initialize(age, active_years, veteran)
@age = age
@active_years = active_years
@veteran = veteran
end
def can_retire?
return true if @age >= 67
return true if @active_years >= 30
return true if @age >= 60 && @active_years >= 25
return true if @veteran && @active_years > 25
false
end
end
প্রথম ধাপটি হবে পরীক্ষার জন্য একটি নতুন ফাইল তৈরি করা, যাতে আমরা সেগুলিকে সেখানে যোগ করা শুরু করতে পারি। আমরা can_retire?
-এর প্রথম লাইন দেখেছি
def can_retire?
return true if @age >= 67
...
...
end
সুতরাং, আমরা প্রথমে এই কেসটি পরীক্ষা করতে পারি:
# specs/worker_spec.rb
require_relative './../worker'
describe Worker do
describe 'can_retire?' do
it "should return true if age is higher than 67" do
end
end
end
এখানে একটি দ্রুত টিপ:আপনি যখন TCR-এর সাথে কাজ করছেন, প্রতিবার সংরক্ষণ করার সময়, পরীক্ষাগুলি পাস না হলে সর্বশেষ পরিবর্তনগুলি অদৃশ্য হয়ে যাবে। অতএব, আমরা সত্যই লেখার আগে এবং দাবির সাথে লাইন বা লাইনগুলি সংরক্ষণ করার আগে পরীক্ষাটি "সেট আপ" করার জন্য যতটা সম্ভব কোড রাখতে চাই৷
যদি আমরা উপরের ফাইলটি সেভ করি, তাহলে আমরা পরীক্ষার জন্য একটি লাইন যোগ করতে পারি।
require_relative './../worker'
describe Worker do
describe 'can_retire?' do
it "should return true if age is higher than 67" do
expect(Worker.new(70, 10, false).can_retire?).to be_true ## This line can disappear when we save now
end
end
end
যখন আমরা সংরক্ষণ করি, যদি নতুন লাইনটি অদৃশ্য না হয়, আমরা একটি ভাল কাজ করেছি; পরীক্ষা পাস!
আরো পরীক্ষা যোগ করা হচ্ছে
একবার আমাদের প্রথম পরীক্ষা হয়ে গেলে, আমরা মিথ্যা মামলা বিবেচনা করে আরও কেস যোগ করতে পারি। কিছু কাজ করার পরে, আমাদের কাছে এরকম কিছু আছে:
# frozen_string_literal: true
require_relative './../worker'
describe Worker do
describe 'can_retire?' do
it 'should return true if age is higher than 67' do
expect(Worker.new(70, 10, false).can_retire?).to be true
end
it 'should return true if age is 67' do
expect(Worker.new(67, 10, false).can_retire?).to be true
end
it 'should return true if age is less than 67' do
expect(Worker.new(50, 10, false).can_retire?).to be false
end
it 'should return true if active years is higher than 30' do
expect(Worker.new(60, 31, false).can_retire?).to be true
end
it 'should return true if active years is 30' do
expect(Worker.new(60, 30, false).can_retire?).to be true
end
end
end
প্রতিটি ক্ষেত্রে, আমরা প্রথমে "এটি" ব্লক লিখি, সংরক্ষণ করি এবং তারপরে expect(...)
দিয়ে দাবী যোগ করি। .
যথারীতি, আমরা যতটা সম্ভব পরীক্ষা যোগ করতে পারি, কিন্তু সব কিছু কভার করা হয়েছে কিনা তা তুলনামূলকভাবে নিশ্চিত হয়ে গেলে অনেকগুলি যোগ করা এড়াতে এটা বোধগম্য।
কভার করার জন্য এখনও কয়েকটি কেস আছে, তাই সম্পূর্ণতার জন্য আমাদের সেগুলি যোগ করা উচিত৷
চূড়ান্ত পরীক্ষা
এখানে বিশেষ ফাইলটি তার চূড়ান্ত আকারে রয়েছে। আপনি দেখতে পাচ্ছেন, আমরা এখনও আরও কেস যোগ করতে পারি, কিন্তু আমি মনে করি এটিই টিসিআর প্রক্রিয়াটি ব্যাখ্যা করার জন্য যথেষ্ট।
# frozen_string_literal: true
require_relative './../worker'
describe Worker do
describe 'can_retire?' do
it 'should return true if age is higher than 67' do
expect(Worker.new(70, 10, false).can_retire?).to be true
end
it 'should return true if age is 67' do
expect(Worker.new(67, 10, false).can_retire?).to be true
end
it 'should return true if age is less than 67' do
expect(Worker.new(50, 10, false).can_retire?).to be false
end
it 'should return true if active years is higher than 30' do
expect(Worker.new(60, 31, false).can_retire?).to be true
end
it 'should return true if active years is 30' do
expect(Worker.new(20, 30, false).can_retire?).to be true
end
it 'should return true if age is higher than 60 and active years is higher than 25' do
expect(Worker.new(60, 30, false).can_retire?).to be true
end
it 'should return true if age is higher than 60 and active years is higher than 25' do
expect(Worker.new(61, 30, false).can_retire?).to be true
end
it 'should return true if age is 60 and active years is higher than 25' do
expect(Worker.new(60, 30, false).can_retire?).to be true
end
it 'should return true if age is higher than 60 and active years is 25' do
expect(Worker.new(61, 25, false).can_retire?).to be true
end
it 'should return true if age is 60 and active years is 25' do
expect(Worker.new(60, 25, false).can_retire?).to be true
end
it 'should return true if is veteran and active years is higher than 25' do
expect(Worker.new(60, 25, false).can_retire?).to be true
end
end
end
রিফ্যাক্টরের উপায়
আপনি যদি এই পর্যন্ত পড়ে থাকেন তবে সম্ভবত এমন কিছু আছে যা কোডের সাথে কিছুটা বন্ধ অনুভব করে। আমাদের অনেক "জাদুকরী সংখ্যা" আছে যেগুলোকে পরীক্ষায় এবং কর্মী শ্রেণী উভয় ক্ষেত্রেই ধ্রুবক হিসাবে বের করা উচিত।
আমরা মূল ক্যান_রিটায়ারে প্রতিটি ক্ষেত্রে ব্যক্তিগত পদ্ধতিও তৈরি করতে পারি? পাবলিক পদ্ধতি।
আমি আপনার জন্য ব্যায়াম হিসাবে সম্ভাব্য উভয় রিফ্যাক্টরিং ছেড়ে দেব। যাইহোক, আমাদের এখন পরীক্ষা আছে, তাই আমরা যদি কোন ধাপে ভুল করি, তারা আমাদের জানাবে।
সিদ্ধান্ত
আমি আপনাকে আপনার প্রকল্পগুলির সাথে TCR চেষ্টা করার জন্য উত্সাহিত করি। এটি একটি খুব সস্তা পরীক্ষা কারণ আপনার একটি বহিরাগত সার্ভারে কোন অভিনব ক্রমাগত একীকরণ বা একটি নতুন লাইব্রেরির সাথে নির্ভরতার প্রয়োজন নেই। আপনার কম্পিউটারে নির্দিষ্ট ফাইল সংরক্ষণ করার সময় আপনার যা দরকার তা হল একটি কমান্ড কার্যকর করার একটি উপায়৷
পরীক্ষাগুলি যোগ করার সময় এটি আপনাকে একটি "গেমিং" অভিজ্ঞতা দেবে, যা সর্বদা মজাদার এবং আকর্ষণীয়। অতিরিক্তভাবে, আপনার সম্পাদক থেকে ব্যর্থ পরীক্ষাগুলি সরানোর শৃঙ্খলা আপনাকে সংগ্রহস্থলে যে পরীক্ষাগুলি ঠেলে দিচ্ছেন তা উত্তীর্ণ হচ্ছে তা নিশ্চিত করার মাধ্যমে আপনাকে একটি অতিরিক্ত নিরাপত্তা জাল দেবে৷
আমি আশা করি উত্তরাধিকার কোডের সাথে কাজ করার সময় আপনি এই নতুন কৌশলটি দরকারী বলে মনে করেন। আমি গত কয়েক মাসে একাধিকবার ব্যবহার করেছি, এবং এটা সবসময়ই আনন্দের।
অতিরিক্ত সম্পদ
- পরিচয় হিসেবে ভালো ভিডিও।
- ভিএস কোডে টিসিআর কীভাবে ব্যবহার করতে হয় সে সম্পর্কে কেন্ট বেকের সিদ্ধান্ত।
- সেভ করার সময় স্ক্রিপ্ট চালানোর জন্য VS কোডের প্লাগইন।