วิธีจัดการพารามิเตอร์ส่วนกลางอย่างถูกต้องสำหรับการทดสอบหน่วยในงูใหญ่?


11

เรากำลังใช้อัลกอริทึมมากมายซึ่งโดยทั่วไปจะมีพารามิเตอร์ที่แชร์สาธารณะรู้จักและความปลอดภัย

ปัจจุบันเราใช้คลาสที่เก็บพารามิเตอร์ทั้งหมดและวัตถุโกลบอลที่กำหนดไว้ล่วงหน้าสองรายการ:

class PublicParams(object):
    p = q = 0

    def __init__(self, p, q):
        self.p = p
        self.q = q

# used for tests
publicParams_test = PublicParams(15,7)               

# Some 2048 bit numbers for example
publicParams_secure = PublicParams(128378947298374928374,128378947298374928374)  

จากนั้นอัลกอริธึมนำPublicParamsวัตถุเป็นอาร์กิวเมนต์ที่เป็นค่าเริ่มต้นไปยังการผลิตpublicParams_secure

def AlgoOne(n, publicParams = publicParams_secure):
    # do stuff with publicParams.p
    # ...
    AlgoTwo(x, publicParams)

และ

def AlgoTwo(x, publicParams= publicParams_secure):
    # do stuff with publicParams.q

วิธีนี้เรายังสามารถฉีดพารามิเตอร์สาธารณะที่แตกต่างกันเพื่อการทดสอบหน่วยที่ง่ายขึ้น:

class AlgoOneTest(unittest.TestCase):
    def test(self):
        # compare with manually computed result
        self.assertTrue(AlgoOne(1, publicParams_test) == 10) 

สิ่งที่ฉันไม่ชอบเกี่ยวกับวิธีการนี้:

  • การให้publicParamsค่าเริ่มต้นทำให้เป็นตัวเลือกเมื่อเรียกอัลกอริทึม อย่างไรก็ตามมันจะกลายเป็นเรื่องง่ายที่จะลืมผ่านมันเมื่อโทรAlgoTwoจากภายในAlgoOneซึ่งจะส่งผลให้วัตถุที่แตกต่างกันสองถูกนำมาใช้ถ้าวัตถุทดสอบถูกส่งผ่านไปยังAlgoOne

มีวิธีที่ดีกว่าซึ่งมีแนวโน้มน้อยกว่า แต่ยังมีความยืดหยุ่นสำหรับการทดสอบหน่วย? นี่เป็นวิธีปฏิบัติที่ดีที่สุดจริง ๆ หรือ

คำตอบ:


1

สร้างแฟ้มการกำหนดค่าและtest_config.py production_config.pyเลือกหนึ่งในนั้นโดยใช้ตัวแปรสภาพแวดล้อมหรืออาร์กิวเมนต์บรรทัดคำสั่ง นำเข้ามัน (หรืออ่าน / แยกถ้าคุณเลือก.json/ .txtแทน.py) และทำให้ผลลัพธ์สามารถใช้ได้กับโปรแกรมทั้งหมดผ่านวัตถุทั่วโลกในโมดูลที่คุณสามารถนำเข้าได้ทุกที่

สิ่งนี้คล้ายกับสิ่งที่คุณทำอยู่แล้วยกเว้นว่ามันจะเพิ่มอีกขั้นหนึ่งจากขอบเขตทั่วโลกไปจนถึงเชลล์ที่คุณเรียกใช้ไพ ธ อน ข้อได้เปรียบคือไม่มีความเสี่ยงในการรวมการผลิตและการกำหนดค่าการทดสอบโดยไม่ได้ตั้งใจอีกต่อไป: คุณไม่สามารถอ่านไฟล์ทั้งสองในเซสชันหลามเดียวกันได้เนื่องจากมีตัวแปรสภาพแวดล้อม / บรรทัดคำสั่งเดียวเท่านั้น


0

มีหลายสิ่งที่คุณสามารถทำได้

  • หยุดใช้ globals
  • หยุดใช้ค่าเริ่มต้น
  • ทดสอบผ่านตัวช่วยส่วนตัวที่ไม่อนุญาตให้ใช้ค่าเริ่มต้นเสมอ

    def _AlgoOne(n, publicParams):
        return AlgoOne(n, publicParams)

แน่นอนว่าตัวเลือกเหล่านั้นมีงานมากมาย แต่คุณจะไม่ถามว่าสิ่งนี้เป็นปัญหาสำหรับคุณหรือไม่


0

หนึ่งสามารถแยกคอลเลกชันของค่าจากบริบททั่วโลกและการประมวลผลของพารามิเตอร์เหล่านั้น

def do_the_thing():
    """Provides the public (rather untestable) context.
    _do_the_thing(global1, global2, publicParams)"""

def _do_the_thing(blah, blah, blah):
    "Actually does the thing"
    pass
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.