Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เข้าใจ Minitest: มันทำงานอย่างไรใน Ruby

Minitest คืออะไร?

Minitest เป็น Ruby testing library ช่วยให้คุณเขียน test สำหรับโค้ดได้แบบ TDD

มันคือ default testing framework ของ Rails และเป็นที่ชอบของ DHH

บางคนชอบมันเพราะความเรียบง่าย และโค้ดน้อยกว่าตัวเลือกหลัก (RSpec) มาก

ดูจากรูปนี้:

เข้าใจ Minitest: มันทำงานอย่างไรใน Ruby

บทความนี้ไม่ได้เกี่ยวกับว่าควรเลือกตัวไหนหรือตัวไหน "ดีกว่า"

บทความนี้เกี่ยวกับ Minitest ทำงานอย่างไร

ถ้าคุณสงสัย: ใช้ตัวไหนก็ได้ที่คุณชอบ แต่น่าจะคุ้นเคยทั้งคู่ 🙂

ถ้าคุณชอบเรียนรู้ว่าสิ่งต่างๆ ทำงานยังไง คุณจะชอบบทความนี้...

ไม่ว่าคุณจะชอบ testing library ตัวไหน!

มาดูภายใต้ฝาฝน (Under The Hood)

หนึ่งในสิ่งที่แนะนำ (รวมถึงผม) คือ อ่าน source code เพราะมันเป็นวิธีดีๆ เรียนรู้ว่าสิ่งต่างๆ ทำงานยังไง และยังเรียนรู้ Ruby tricks ใหม่ๆ ที่อาจไม่เคยเห็น

นั่นคือสิ่งที่ผมทำกับ Minitest และจะแชร์สิ่งที่เรียนรู้

เริ่มจากโค้ด test จริงๆ เพื่อดูว่าเกี่ยวข้องกับวิธีการทำงานของ Minitest อย่างไร

class Thingy < Minitest::Test
  def test_it_works
    assert_equal 1, 1
  end
end

Minitest หา testing methods (อย่าง test_it_works) และรันมันได้อย่างไร?

คำตอบคือเล็กน้อยของ metaprogramming "magic":

def self.methods_matching(re)
  public_instance_methods(true).grep(re).map(&:to_s)
end

โค้ดนี้มาจากคลาส Runnable ที่กำหนดใน lib/minitest.rb โค้ดนี้หา instance methods ทั้งหมดของคลาสปัจจุบัน และเลือกเฉพาะที่ match regular expression

ดังนั้นถ้าเรียก methods_matching(/^test_/) จะได้อาร์เรย์ของชื่อเมธอดทั้งหมดที่ขึ้นต้นด้วย test_

Minitest ทำงานอย่างไร

Minitest หาเมธอด test_ แล้วเรียกมัน

เกิดขึ้นในไฟล์ lib/minitest/test.rb (เฉพาะเจาะจงที่เมธอด runnable_methods ซึ่งคืนรายการเมธอดแบบสุ่ม)

จุดสำคัญ:
นี่ทำงานได้เพราะ Minitest::Test เป็น subclass ของ Runnable

ชิ้นส่วนสุดท้ายคือ class method run บน Runnable ซึ่ง filter เพิ่มเติม แล้วเรียก run_one_method กับทุกชื่อเมธอดและ reporter object

โค้ด:

filtered_methods.each do |method_name|
  run_one_method self, method_name, reporter
end

และสิ้นสุดที่การเรียก instance method run บน Minitest::Test:

capture_exceptions do
  before_setup; setup; after_setup
  self.send self.name
end

send เป็นเมธอด metaprogramming ให้เรียกเมธอดอื่นบนออบเจ็กต์ใดๆ ด้วย string หรือ symbol

บล็อก capture_exceptions ใช้บันทึก test failures และ exceptions ที่โค้ดของคุณ raise

def capture_exceptions # :nodoc:
  yield
rescue *PASSTHROUGH_EXCEPTIONS
  raise
rescue Assertion => e
  self.failures << e
rescue Exception => e
  self.failures << UnexpectedError.new(e)
end

วิธีอ่านโค้ดที่ผมชอบคือ โฟกัสที่ด้านหนึ่งหรือฟีเจอร์หนึ่ง แล้วปอกเปลือกทีละชั้นเหมือนหอมใหญ่

ถ้าไม่รู้ว่าอะไรหมายถึงอะไร (อย่าง keyword yield) ให้ไปค้นหา มันเป็นส่วนหนึ่งของการเรียนรู้!

สรุป

ในบทความนี้ คุณเรียนรู้ว่า Minitest ใช้ metaprogramming หา test methods และเรียกมัน รวมถึงวิธีจับ test errors และ exceptions ไว้ในอาร์เรย์เพื่อรายงาน

คุณชอบบทความประเภท "วิเคราะห์โค้ด" แบบนี้ไหม?

บอกมาในคอมเมนต์ 🙂

และ อย่าลืมแชร์บนโซเชียลมีเดียโปรดของคุณ และสมัครรับข่าวสารด้านล่างถ้ายังไม่ได้เป็นส่วนหนึ่งของ 7000+ Ruby developers ที่อยากพัฒนาทักษะ!