คุณมีสิทธิ์ทดสอบของคุณไม่ควรตรวจสอบว่าrandom
โมดูลทำงาน unittest ควรทดสอบคลาสเองเท่านั้นไม่ใช่วิธีโต้ตอบกับโค้ดอื่น ๆ (ซึ่งควรทดสอบแยกต่างหาก)
เป็นไปได้อย่างแน่นอนว่ารหัสของคุณใช้random.randint()
ผิด หรือคุณจะโทรมาrandom.randrange(1, self._sides)
แทนและความตายของคุณจะไม่ส่งผ่านค่าสูงสุด แต่นั่นเป็นข้อผิดพลาดประเภทอื่นไม่ใช่คนที่คุณสามารถจับได้ด้วยความไม่สุภาพ ในกรณีดังกล่าวdie
หน่วยของคุณทำงานตามที่ได้ออกแบบไว้ แต่การออกแบบนั้นมีข้อบกพร่อง
ในกรณีนี้ฉันต้องการใช้เยาะเย้ยเพื่อแทนที่randint()
ฟังก์ชั่นและมีเพียงตรวจสอบว่าได้รับการเรียกว่าได้อย่างถูกต้อง Python 3.3 ขึ้นไปมาพร้อมกับunittest.mock
โมดูลเพื่อจัดการกับการทดสอบประเภทนี้ แต่คุณสามารถติดตั้งmock
แพ็กเกจภายนอกในเวอร์ชั่นเก่ากว่าเพื่อรับฟังก์ชั่นที่แน่นอน
import unittest
try:
from unittest.mock import patch
except ImportError:
# < python 3.3
from mock import patch
@patch('random.randint', return_value=3)
class TestDice(unittest.TestCase):
def _make_one(self, *args, **kw):
from die import Die
return Die(*args, **kw)
def test_standard_size(self, mocked_randint):
die = self._make_one()
result = die.roll()
mocked_randint.assert_called_with(1, 6)
self.assertEqual(result, 3)
def test_custom_size(self, mocked_randint):
die = self._make_one(sides=42)
result = die.roll()
mocked_randint.assert_called_with(1, 42)
self.assertEqual(result, 3)
if __name__ == '__main__':
unittest.main()
ด้วยการล้อเลียนการทดสอบของคุณก็ง่ายมาก มีเพียง 2 รายเท่านั้นจริงๆ กรณีเริ่มต้นสำหรับตาย 6 ด้านและกรณีด้านที่กำหนดเอง
มีวิธีอื่นในการแทนที่randint()
ฟังก์ชันในเนมสเปซส่วนกลางของชั่วคราวDie
แต่mock
โมดูลทำให้สิ่งนี้ง่ายที่สุด @mock.patch
มัณฑนากรที่นี่นำไปใช้ทุกวิธีการทดสอบในกรณีการทดสอบ; แต่ละวิธีการทดสอบจะถูกส่งผ่านอาร์กิวเมนต์พิเศษrandom.randint()
ฟังก์ชั่นที่เยาะเย้ยดังนั้นเราสามารถทดสอบกับจำลองเพื่อดูว่ามันถูกเรียกอย่างถูกต้องหรือไม่ return_value
อาร์กิวเมนต์ระบุสิ่งที่กลับมาจากการเยาะเย้ยเมื่อมันถูกเรียกว่าเพื่อให้เราสามารถตรวจสอบว่าdie.roll()
วิธีการที่แน่นอนกลับ 'สุ่ม' ผลให้เรา
ฉันใช้ Python อีกวิธีที่ดีที่สุดที่นี่: นำเข้าชั้นเรียนภายใต้การทดสอบเป็นส่วนหนึ่งของการทดสอบ _make_one
วิธีการทำการนำเข้าและการเริ่มการทำงานภายในการทดสอบเพื่อให้การทดสอบโมดูลจะยังคงโหลดแม้ว่าคุณจะทำผิดพลาดทางไวยากรณ์หรือความผิดพลาดอื่น ๆ ที่จะป้องกันไม่ให้โมดูลเดิมจะนำเข้า
วิธีนี้ถ้าคุณทำผิดพลาดในรหัสโมดูลเองการทดสอบจะยังคงทำงานอยู่ พวกเขาจะล้มเหลวโดยบอกคุณเกี่ยวกับข้อผิดพลาดในรหัสของคุณ
เพื่อความชัดเจนการทดสอบข้างต้นนั้นง่ายมากในสุดขั้ว เป้าหมายที่นี่ไม่ใช่การทดสอบที่random.randint()
ถูกเรียกด้วยอาร์กิวเมนต์ที่ถูกต้องตัวอย่างเช่น เป้าหมายคือการทดสอบว่าหน่วยกำลังสร้างผลลัพธ์ที่ถูกต้องจากอินพุตบางตัวโดยที่อินพุตเหล่านั้นรวมผลลัพธ์ของหน่วยอื่น ๆ ที่ไม่ได้ทดสอบ โดยการเยาะเย้ยrandom.randint()
วิธีการที่คุณจะควบคุมเพียงแค่การป้อนข้อมูลอื่นในรหัสของคุณ
ในการทดสอบในโลกแห่งความเป็นจริงรหัสจริงในการทดสอบหน่วยของคุณจะมีความซับซ้อนมากขึ้น ความสัมพันธ์กับอินพุตที่ส่งผ่านไปยัง API และวิธีการเรียกใช้หน่วยอื่น ๆ นั้นน่าสนใจและการเยาะเย้ยจะทำให้คุณสามารถเข้าถึงผลลัพธ์ระดับกลางได้เช่นเดียวกับให้คุณตั้งค่าส่งคืนสำหรับการโทรเหล่านั้น
ตัวอย่างเช่นในรหัสที่รับรองความถูกต้องผู้ใช้กับบริการ OAuth2 ของบุคคลที่สาม (การโต้ตอบหลายขั้นตอน) คุณต้องการทดสอบว่ารหัสของคุณส่งข้อมูลที่ถูกต้องไปยังบริการบุคคลที่สามนั้นและให้คุณจำลองการตอบสนองข้อผิดพลาดต่างๆ บริการของบุคคลที่สามจะกลับมาให้คุณจำลองสถานการณ์ที่แตกต่างกันโดยไม่ต้องสร้างเซิร์ฟเวอร์ OAuth2 แบบเต็มด้วยตัวเอง นี่เป็นสิ่งสำคัญที่จะต้องทดสอบว่าข้อมูลจากการตอบกลับครั้งแรกได้รับการจัดการอย่างถูกต้องและถูกส่งต่อไปยังการเรียกขั้นที่สองดังนั้นคุณต้องการดูว่าบริการการเยาะเย้ยนั้นถูกเรียกอย่างถูกต้องหรือไม่