แนวทางปฏิบัติที่แนะนำสำหรับการทดสอบโค้ดใน พื้นที่เก็บข้อมูล TensorFlow มีดังนี้
ก่อนที่คุณจะเริ่มต้น
ก่อนที่คุณจะสนับสนุนซอร์สโค้ดให้กับโปรเจ็กต์ TensorFlow โปรดตรวจสอบไฟล์ CONTRIBUTING.md
ในที่เก็บ GitHub ของโปรเจ็กต์ (ตัวอย่างเช่น ดู ไฟล์ CONTRIBUTING.md สำหรับ repo TensorFlow หลัก ) ผู้ร่วมเขียนโค้ดทุกคนจะต้องลงนามใน ข้อตกลงใบอนุญาตผู้ร่วมให้ข้อมูล (CLA)
หลักการทั่วไป
ขึ้นอยู่กับสิ่งที่คุณใช้ในกฎ BUILD ของคุณเท่านั้น
TensorFlow เป็นไลบรารีขนาดใหญ่ และขึ้นอยู่กับแพ็คเกจเต็มเมื่อเขียน Unit Test สำหรับโมดูลย่อยถือเป็นแนวทางปฏิบัติทั่วไป อย่างไรก็ตาม การดำเนินการนี้จะปิดใช้งานการวิเคราะห์ตามการพึ่งพา bazel
ซึ่งหมายความว่าระบบบูรณาการอย่างต่อเนื่องไม่สามารถกำจัดการทดสอบที่ไม่เกี่ยวข้องสำหรับการดำเนินการก่อนส่ง/หลังส่งได้อย่างชาญฉลาด หากคุณพึ่งพาเฉพาะโมดูลย่อยที่คุณกำลังทดสอบในไฟล์ BUILD
ของคุณ คุณจะประหยัดเวลาสำหรับนักพัฒนา TensorFlow ทั้งหมด และพลังการคำนวณอันมีค่ามากมาย
อย่างไรก็ตาม การแก้ไขการพึ่งพาบิวด์ของคุณเพื่อละเว้นเป้าหมาย TF แบบเต็มทำให้เกิดข้อจำกัดบางประการสำหรับสิ่งที่คุณสามารถนำเข้าในโค้ด Python ของคุณได้ คุณจะไม่สามารถใช้ import tensorflow as tf
ในการทดสอบหน่วยของคุณได้อีกต่อไป แต่นี่เป็นการแลกเปลี่ยนที่คุ้มค่า เนื่องจากช่วยให้นักพัฒนาทุกคนไม่ต้องทำการทดสอบที่ไม่จำเป็นนับพันครั้ง
รหัสทั้งหมดควรมีการทดสอบหน่วย
สำหรับโค้ดใดๆ ที่คุณเขียน คุณควรเขียน Unit Tests ด้วย หากคุณเขียนไฟล์ใหม่ foo.py
คุณควรวาง unit tests ใน foo_test.py
และส่งภายในการเปลี่ยนแปลงเดียวกัน ตั้งเป้าให้ครอบคลุมการทดสอบเพิ่มขึ้น >90% สำหรับโค้ดทั้งหมดของคุณ
หลีกเลี่ยงการใช้กฎการทดสอบ bazel ดั้งเดิมใน TF
TF มีรายละเอียดปลีกย่อยมากมายเมื่อทำการทดสอบ เราได้ทำงานเพื่อซ่อนความซับซ้อนเหล่านั้นทั้งหมดในมาโคร Bazel ของเรา เพื่อหลีกเลี่ยงการจัดการกับสิ่งเหล่านั้น ให้ใช้สิ่งต่อไปนี้แทนกฎการทดสอบดั้งเดิม โปรดทราบว่าสิ่งเหล่านี้ทั้งหมดถูกกำหนดไว้ใน tensorflow/tensorflow.bzl
สำหรับการทดสอบ CC ให้ใช้ tf_cc_test
, tf_gpu_cc_test
, tf_gpu_only_cc_test
สำหรับการทดสอบหลาม ให้ใช้ tf_py_test
หรือ gpu_py_test
หากคุณต้องการบางสิ่งที่ใกล้เคียงกับกฎ py_test
ดั้งเดิมมาก โปรดใช้กฎที่กำหนดไว้ใน tensorflow.bzl แทน คุณเพียงแค่ต้องเพิ่มบรรทัดต่อไปนี้ที่ด้านบนของไฟล์ BUILD: load(“tensorflow/tensorflow.bzl”, “py_test”)
โปรดทราบว่าการทดสอบจะดำเนินการที่ไหน
เมื่อคุณเขียนการทดสอบ อินฟราทดสอบของเราจะดูแลการทดสอบของคุณบน CPU, GPU และตัวเร่งความเร็ว หากคุณเขียนการทดสอบเหล่านั้นตามนั้น เรามีการทดสอบอัตโนมัติที่ทำงานบน Linux, MacOS, Windows ซึ่งมีระบบที่มีหรือไม่มี GPU คุณเพียงแค่ต้องเลือกมาโครตัวใดตัวหนึ่งที่แสดงไว้ด้านบน จากนั้นใช้แท็กเพื่อจำกัดตำแหน่งที่จะดำเนินการ
แท็ก
manual
จะแยกการทดสอบของคุณไม่ให้ทำงานที่ใดก็ได้ ซึ่งรวมถึงการดำเนินการทดสอบด้วยตนเองที่ใช้รูปแบบ เช่นbazel test tensorflow/…
no_oss
จะแยกการทดสอบของคุณออกจากการทำงานในโครงสร้างพื้นฐานการทดสอบ TF OSS อย่างเป็นทางการแท็ก
no_mac
หรือno_windows
สามารถใช้เพื่อยกเว้นการทดสอบของคุณจากชุดการทดสอบระบบปฏิบัติการที่เกี่ยวข้องแท็ก
no_gpu
สามารถใช้เพื่อแยกการทดสอบของคุณไม่ให้ทำงานในชุดการทดสอบ GPU
ตรวจสอบการทดสอบที่ทำงานในชุดการทดสอบที่คาดไว้
TF มีชุดทดสอบค่อนข้างน้อย บางครั้งอาจสร้างความสับสนในการตั้งค่า อาจมีปัญหาที่แตกต่างกันซึ่งทำให้การทดสอบของคุณถูกละเว้นจากการสร้างอย่างต่อเนื่อง ดังนั้น คุณควรตรวจสอบว่าการทดสอบของคุณดำเนินการตามที่คาดไว้ เมื่อต้องการทำสิ่งนี้:
- รอให้การส่งคำขอดึงล่วงหน้า (PR) ของคุณดำเนินการให้เสร็จสิ้น
- เลื่อนไปที่ด้านล่างของ PR ของคุณเพื่อดูการตรวจสอบสถานะ
- คลิกลิงก์ "รายละเอียด" ที่ด้านขวาของเช็ค Kokoro
- ตรวจสอบรายการ "เป้าหมาย" เพื่อค้นหาเป้าหมายที่เพิ่มใหม่ของคุณ
แต่ละชั้นเรียน/หน่วยควรมีไฟล์ทดสอบหน่วยของตนเอง
ชั้นเรียนการทดสอบที่แยกจากกันช่วยให้เราแยกความล้มเหลวและทรัพยากรได้ดีขึ้น ทำให้ไฟล์ทดสอบสั้นลงและอ่านง่ายขึ้นมาก ดังนั้น ไฟล์ Python ทั้งหมดของคุณควรมีไฟล์ทดสอบที่เกี่ยวข้องอย่างน้อยหนึ่งไฟล์ (สำหรับแต่ละ foo.py
ควรมี foo_test.py
) สำหรับการทดสอบที่ซับซ้อนมากขึ้น เช่น การทดสอบการรวมที่ต้องมีการตั้งค่าที่แตกต่างกัน คุณสามารถเพิ่มไฟล์ทดสอบเพิ่มเติมได้
ความเร็วและระยะเวลาการทำงาน
ควรใช้เศษให้น้อยที่สุด
แทนที่จะแบ่งย่อย โปรดพิจารณา:
- ทำให้การทดสอบของคุณเล็กลง
- หากเป็นไปไม่ได้ ให้แยกการทดสอบออก
Sharding ช่วยลดเวลาแฝงโดยรวมของการทดสอบ แต่ก็สามารถทำได้เช่นกันโดยการแบ่งการทดสอบออกเป็นเป้าหมายที่เล็กลง การทดสอบแบบแยกส่วนช่วยให้เราควบคุมการทดสอบแต่ละครั้งได้ในระดับที่ละเอียดยิ่งขึ้น ลดการรันการส่งล่วงหน้าที่ไม่จำเป็น และลดการสูญเสียความครอบคลุมจาก Buildcop ที่ทำให้เป้าหมายทั้งหมดไม่ทำงานเนื่องจากกรณีทดสอบทำงานผิดปกติ ยิ่งไปกว่านั้น การแบ่งส่วนทำให้เกิดค่าใช้จ่ายแอบแฝงซึ่งไม่ชัดเจนนัก เช่น การรันโค้ดเริ่มต้นการทดสอบทั้งหมดสำหรับส่วนแบ่งทั้งหมด ปัญหานี้ได้รับการยกระดับถึงเราโดยทีมอินฟาเรดซึ่งเป็นต้นเหตุที่สร้างภาระงานพิเศษ
การทดสอบขนาดเล็กจะดีกว่า
ยิ่งการทดสอบของคุณดำเนินการเร็วเท่าใด ผู้คนก็จะยิ่งทำการทดสอบของคุณมากขึ้นเท่านั้น วินาทีที่เพิ่มขึ้นมาสำหรับการทดสอบของคุณสามารถสะสมเป็นชั่วโมงของเวลาพิเศษที่นักพัฒนาซอฟต์แวร์และโครงสร้างพื้นฐานของเราใช้ในการทดสอบ พยายามทำให้การทดสอบของคุณใช้เวลาไม่เกิน 30 วินาที (ในโหมดที่ไม่ใช่ตัวเลือก!) และทำให้การทดสอบมีขนาดเล็ก ทำเครื่องหมายการทดสอบของคุณว่าเป็นสื่อเป็นทางเลือกสุดท้ายเท่านั้น อินฟราไม่ได้ทำการทดสอบขนาดใหญ่ใดๆ ทั้งแบบส่งล่วงหน้าหรือส่งภายหลัง! ดังนั้น ให้เขียนการทดสอบขนาดใหญ่เฉพาะในกรณีที่คุณต้องการจัดว่าการทดสอบจะดำเนินการที่ใด เคล็ดลับบางประการในการทำให้การทดสอบทำงานเร็วขึ้น:
- ฝึกซ้ำให้น้อยลงในการทดสอบของคุณ
- พิจารณาใช้การพึ่งพาการฉีดเพื่อแทนที่การพึ่งพาอย่างมากของระบบภายใต้การทดสอบด้วยการปลอมแบบธรรมดา
- พิจารณาใช้ข้อมูลอินพุตที่มีขนาดเล็กกว่าในการทดสอบหน่วย
- หากไม่มีสิ่งใดได้ผล ให้ลองแยกไฟล์ทดสอบของคุณ
เวลาทดสอบควรมุ่งเป้าไปที่ครึ่งหนึ่งของระยะหมดเวลาของขนาดการทดสอบเพื่อหลีกเลี่ยงการสะเก็ด
ด้วยเป้าหมายการทดสอบ bazel
การทดสอบขนาดเล็กจะมีระยะหมดเวลา 1 นาที ระยะหมดเวลาการทดสอบปานกลางคือ 5 นาที การทดสอบขนาดใหญ่ไม่ได้ดำเนินการโดยอินฟราการทดสอบ TensorFlow อย่างไรก็ตาม การทดสอบจำนวนมากไม่สามารถกำหนดระยะเวลาได้ ด้วยเหตุผลหลายประการ การทดสอบของคุณอาจใช้เวลานานขึ้นเป็นครั้งคราว และหากคุณทำเครื่องหมายการทดสอบที่ทำงานเป็นเวลา 50 วินาทีโดยเฉลี่ยว่ามีขนาดเล็ก การทดสอบของคุณจะหลุดออกหากจัดกำหนดการบนเครื่องที่มี CPU เก่า ดังนั้นให้ตั้งเป้าเวลาทำงานเฉลี่ย 30 วินาทีสำหรับการทดสอบเล็กๆ น้อยๆ ตั้งเป้าไว้ที่ 2 นาที 30 วินาทีของเวลาวิ่งโดยเฉลี่ยสำหรับการทดสอบระดับกลาง
ลดจำนวนตัวอย่างและเพิ่มเกณฑ์ความคลาดเคลื่อนในการฝึกอบรม
การทดสอบที่ทำงานช้าจะขัดขวางผู้มีส่วนร่วม การฝึกซ้อมในการทดสอบอาจทำได้ช้ามาก ต้องการความคลาดเคลื่อนที่สูงขึ้นเพื่อให้สามารถใช้ตัวอย่างน้อยลงในการทดสอบของคุณ เพื่อให้การทดสอบของคุณรวดเร็วเพียงพอ (สูงสุด 2.5 นาที)
ขจัดความไม่แน่นอนและสะเก็ด
เขียนแบบทดสอบเชิงกำหนด
การทดสอบหน่วยควรถูกกำหนดไว้เสมอ การทดสอบทั้งหมดที่ทำงานบน TAP และกีตาร์ควรดำเนินการในลักษณะเดียวกันทุกครั้ง หากไม่มีการเปลี่ยนแปลงโค้ดที่ส่งผลกระทบต่อการทดสอบเหล่านั้น เพื่อให้มั่นใจในสิ่งนี้ ต่อไปนี้คือประเด็นที่ควรพิจารณา
ทำการสุ่มแหล่งที่มาของการสุ่มเสมอ
ตัวสร้างตัวเลขสุ่มใดๆ หรือแหล่งสุ่มอื่นๆ อาจทำให้เกิดความไม่แน่นอนได้ ดังนั้นแต่ละอย่างจึงต้องเพาะเมล็ด นอกจากจะทำให้การทดสอบมีความไม่สม่ำเสมอน้อยลงแล้ว ยังทำให้การทดสอบทั้งหมดสามารถทำซ้ำได้อีกด้วย วิธีต่างๆ ในการตั้งค่าเมล็ดพืชบางอย่างที่คุณอาจต้องตั้งค่าในการทดสอบ TF คือ:
# Python RNG
import random
random.seed(42)
# Numpy RNG
import numpy as np
np.random.seed(42)
# TF RNG
from tensorflow.python.framework import random_seed
random_seed.set_seed(42)
หลีกเลี่ยงการใช้ sleep
ในการทดสอบแบบมัลติเธรด
การใช้ฟังก์ชัน sleep
หลับในการทดสอบอาจเป็นสาเหตุสำคัญของความไม่แน่นอนได้ โดยเฉพาะอย่างยิ่งเมื่อใช้หลายเธรด การใช้โหมดสลีปเพื่อรอเธรดอื่นจะไม่ถูกกำหนดไว้ นี่เป็นเพราะระบบไม่สามารถรับประกันลำดับการดำเนินการของเธรดหรือกระบวนการที่แตกต่างกันได้ ดังนั้น แนะนำให้ใช้โครงสร้างการซิงโครไนซ์ที่กำหนดขึ้นเอง เช่น mutexes
ตรวจสอบว่าการทดสอบเป็นขุยหรือไม่
Flakes ทำให้ buildcops และนักพัฒนาเสียเวลาหลายชั่วโมง ตรวจพบได้ยากและแก้ไขจุดบกพร่องได้ยาก แม้ว่าจะมีระบบอัตโนมัติในการตรวจจับความไม่แน่นอน แต่ก็จำเป็นต้องสะสมการทดสอบหลายร้อยครั้งก่อนจึงจะสามารถปฏิเสธการทดสอบได้อย่างแม่นยำ แม้ว่าพวกเขาจะตรวจพบ พวกเขาปฏิเสธรายการการทดสอบของคุณ และความครอบคลุมของการทดสอบก็จะหายไป ดังนั้นผู้เขียนทดสอบควรตรวจสอบว่าการทดสอบของพวกเขาไม่สม่ำเสมอหรือไม่เมื่อเขียนแบบทดสอบ ซึ่งสามารถทำได้ง่ายๆ ด้วยการรันการทดสอบด้วยแฟล็ก: --runs_per_test=1000
ใช้ TensorFlowTestCase
TensorFlowTestCase ใช้ความระมัดระวังที่จำเป็น เช่น การเพาะตัวสร้างตัวเลขสุ่มทั้งหมดที่ใช้เพื่อลดความไม่สม่ำเสมอให้มากที่สุด ขณะที่เราค้นพบและแก้ไขแหล่งที่มาของความไม่สม่ำเสมอเพิ่มเติม สิ่งเหล่านี้ทั้งหมดจะถูกเพิ่มลงใน TensorFlowTestCase ดังนั้น คุณควรใช้ TensorFlowTestCase เมื่อเขียนการทดสอบสำหรับ tensorflow TensorFlowTestCase ถูกกำหนดไว้ที่นี่: tensorflow/python/framework/test_util.py
เขียนการทดสอบสุญญากาศ
การทดสอบสุญญากาศไม่จำเป็นต้องใช้ทรัพยากรภายนอก พวกเขาเต็มไปด้วยทุกสิ่งที่พวกเขาต้องการ และพวกเขาเพิ่งเริ่มให้บริการปลอมๆ ที่พวกเขาต้องการ บริการใดๆ นอกเหนือจากการทดสอบของคุณถือเป็นแหล่งที่มาของสิ่งที่ไม่ได้กำหนดไว้ แม้ว่าบริการอื่นๆ จะมีความพร้อมใช้งานถึง 99% แต่เครือข่ายก็อาจเกิดข้อผิดพลาดได้ การตอบสนองของ rpc อาจล่าช้าได้ และคุณอาจได้รับข้อความแสดงข้อผิดพลาดที่อธิบายไม่ได้ บริการภายนอกอาจเป็นแต่ไม่จำกัดเฉพาะ GCS, S3 หรือเว็บไซต์ใดๆ