นี่คือแนวทางปฏิบัติที่แนะนำสำหรับการทดสอบโค้ดในที่ เก็บ TensorFlow
ก่อนที่คุณจะเริ่มต้น
ก่อนที่คุณจะให้ซอร์สโค้ดในโปรเจ็กต์ TensorFlow โปรดตรวจสอบไฟล์ CONTRIBUTING.md
ในที่เก็บ GitHub ของโปรเจ็กต์ (ตัวอย่างเช่นดู ไฟล์ CONTRIBUTING.md สำหรับที่เก็บ TensorFlow หลัก ) ผู้ร่วมให้รหัสทั้งหมดจะต้องลงนามใน ข้อตกลงสิทธิ์การใช้งานผู้สนับสนุน (CLA)
หลักการทั่วไป
ขึ้นอยู่กับสิ่งที่คุณใช้ในกฎ BUILD ของคุณเท่านั้น
TensorFlow เป็นไลบรารีขนาดใหญ่และขึ้นอยู่กับแพ็กเกจทั้งหมดเมื่อเขียนการทดสอบหน่วยสำหรับโมดูลย่อยนั้นถือเป็นแนวทางปฏิบัติทั่วไป อย่างไรก็ตามสิ่งนี้จะปิดใช้งานการวิเคราะห์ตามการพึ่งพา bazel
ซึ่งหมายความว่าระบบการรวมแบบต่อเนื่องไม่สามารถกำจัดการทดสอบที่ไม่เกี่ยวข้องสำหรับการรัน presubmit / postubmit ได้อย่างชาญฉลาด หากคุณพึ่งพาเฉพาะโมดูลย่อยที่คุณกำลังทดสอบในไฟล์ BUILD
ของคุณคุณจะประหยัดเวลาสำหรับนักพัฒนา TensorFlow ทั้งหมดและพลังการคำนวณที่มีค่ามากมาย
อย่างไรก็ตามการแก้ไขการพึ่งพาบิวด์ของคุณเพื่อละเว้นเป้าหมาย TF แบบเต็มทำให้เกิดข้อ จำกัด บางประการสำหรับสิ่งที่คุณสามารถนำเข้าในโค้ด Python ของคุณได้ คุณจะไม่สามารถใช้ import tensorflow as tf
คำสั่ง import tensorflow as tf
ในการทดสอบหน่วยของคุณได้อีกต่อไป แต่นี่เป็นการแลกเปลี่ยนที่คุ้มค่าเนื่องจากช่วยให้นักพัฒนาทุกคนไม่ต้องทำการทดสอบที่ไม่จำเป็นหลายพันครั้ง
รหัสทั้งหมดควรมีการทดสอบหน่วย
สำหรับโค้ดใด ๆ ที่คุณเขียนคุณควรเขียนการทดสอบหน่วยด้วย หากคุณเขียนไฟล์ foo.py
ใหม่คุณควรทำการทดสอบหน่วยใน foo_test.py
และส่งภายในการเปลี่ยนแปลงเดียวกัน ตั้งเป้าให้ครอบคลุมการทดสอบที่เพิ่มขึ้น> 90% สำหรับรหัสทั้งหมดของคุณ
หลีกเลี่ยงการใช้กฎการทดสอบ bazel ดั้งเดิมใน TF
TF มีรายละเอียดปลีกย่อยมากมายเมื่อทำการทดสอบ เราได้พยายามซ่อนความซับซ้อนทั้งหมดนั้นไว้ในมาโครเบเซลของเรา เพื่อหลีกเลี่ยงไม่ให้ต้องจัดการกับสิ่งเหล่านั้นให้ใช้สิ่งต่อไปนี้แทนกฎการทดสอบเนทีฟ โปรดทราบว่าสิ่งเหล่านี้กำหนดไว้ใน tensorflow/tensorflow.bzl
สำหรับการทดสอบ CC ให้ใช้ tf_cc_test
, tf_gpu_cc_test
, tf_gpu_only_cc_test
สำหรับการทดสอบ python ให้ใช้ 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 มีห้องทดสอบค่อนข้างน้อย บางครั้งอาจเกิดความสับสนในการตั้งค่า อาจมีปัญหาที่แตกต่างกันที่ทำให้การทดสอบของคุณถูกละเว้นจากการสร้างแบบต่อเนื่อง ดังนั้นคุณควรตรวจสอบว่าการทดสอบของคุณดำเนินการตามที่คาดไว้ เพื่อทำสิ่งนี้:
- รอให้การส่งล่วงหน้าของคุณใน Pull Request (PR) ของคุณทำงานจนเสร็จสิ้น
- เลื่อนไปที่ด้านล่างของ PR เพื่อดูการตรวจสอบสถานะ
- คลิกลิงก์ "รายละเอียด" ทางด้านขวาของเช็คโคโคโระ
- ตรวจสอบรายการ "เป้าหมาย" เพื่อค้นหาเป้าหมายที่เพิ่มเข้ามาใหม่
แต่ละชั้น / หน่วยควรมีไฟล์ทดสอบหน่วยของตัวเอง
ชั้นเรียนการทดสอบแยกกันช่วยให้เราแยกความล้มเหลวและทรัพยากรได้ดีขึ้น ซึ่งนำไปสู่ไฟล์ทดสอบที่สั้นและอ่านง่ายกว่ามาก ดังนั้นไฟล์ Python ทั้งหมดของคุณควรมีไฟล์ทดสอบที่เกี่ยวข้องอย่างน้อยหนึ่งไฟล์ (สำหรับ foo.py
แต่ละไฟล์ควรมี foo_test.py
) สำหรับการทดสอบที่ละเอียดมากขึ้นเช่นการทดสอบการรวมที่ต้องใช้การตั้งค่าที่แตกต่างกันคุณควรเพิ่มไฟล์ทดสอบเพิ่มเติม
ความเร็วและเวลาทำงาน
ควรใช้ Sharding ให้น้อยที่สุด
แทนการแยกชิ้นส่วนโปรดพิจารณา:
- ทำให้การทดสอบของคุณมีขนาดเล็กลง
- หากไม่สามารถทำได้ข้างต้นให้แยกการทดสอบออก
Sharding ช่วยลดเวลาแฝงโดยรวมของการทดสอบ แต่สามารถทำได้เช่นเดียวกันโดยการแบ่งการทดสอบไปยังเป้าหมายที่เล็กกว่า การทดสอบแบบแยกส่วนช่วยให้เราสามารถควบคุมการทดสอบแต่ละครั้งได้ดีขึ้นโดยลดการดำเนินการส่งล่วงหน้าที่ไม่จำเป็นให้น้อยที่สุดและลดการสูญเสียความครอบคลุมจากการที่บิลด์ค็อปปิดใช้งานเป้าหมายทั้งหมดเนื่องจากการทดสอบทำงานผิดปกติ ยิ่งไปกว่านั้นการชาร์ดยังก่อให้เกิดค่าใช้จ่ายแอบแฝงที่ไม่ชัดเจนเช่นการรันโค้ดการเริ่มต้นทดสอบทั้งหมดสำหรับชาร์ดทั้งหมด ปัญหานี้ได้รับการแจ้งให้เราทราบโดยทีมงานด้านล่างในฐานะแหล่งที่สร้างภาระเพิ่มเติม
การทดสอบขนาดเล็กจะดีกว่า
ยิ่งการทดสอบของคุณดำเนินไปเร็วเท่าไหร่ผู้คนก็จะมีโอกาสดำเนินการทดสอบของคุณมากขึ้นเท่านั้น หนึ่งวินาทีที่เพิ่มขึ้นสำหรับการทดสอบของคุณสามารถสะสมเป็นชั่วโมงของเวลาเพิ่มเติมที่ใช้ในการทดสอบโดยนักพัฒนาและโครงสร้างพื้นฐาน พยายามทำให้การทดสอบของคุณทำงานภายใน 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 และนักพัฒนาต้องเสียเวลาหลายชั่วโมง ตรวจพบได้ยากและแก้ไขจุดบกพร่องได้ยาก แม้ว่าจะมีระบบอัตโนมัติในการตรวจจับการหลุดลอก แต่ก็จำเป็นต้องสะสมการทดสอบหลายร้อยครั้งก่อนจึงจะสามารถทำการทดสอบ denylist ได้อย่างแม่นยำ แม้ว่าพวกเขาจะตรวจพบพวกเขาปฏิเสธการทดสอบของคุณและการครอบคลุมการทดสอบจะหายไป ดังนั้นผู้ทดสอบควรตรวจสอบว่าการทดสอบของพวกเขามีขุยเมื่อเขียนแบบทดสอบหรือไม่ สามารถทำได้อย่างง่ายดายโดยรันการทดสอบของคุณด้วยแฟ --runs_per_test=1000
: --runs_per_test=1000
ใช้ TensorFlowTestCase
TensorFlowTestCase ใช้มาตรการป้องกันที่จำเป็นเช่นการเพาะเครื่องกำเนิดตัวเลขสุ่มทั้งหมดที่ใช้เพื่อลดความเป็นสะเก็ดให้มากที่สุด ในขณะที่เราค้นพบและแก้ไขแหล่งที่มาของความไม่สมบูรณ์มากขึ้นสิ่งเหล่านี้จะถูกเพิ่มลงใน TensorFlowTestCase ดังนั้นคุณควรใช้ TensorFlowTestCase เมื่อเขียนการทดสอบสำหรับเทนเซอร์โฟลว์ TensorFlowTestCase ถูกกำหนดไว้ที่นี่: tensorflow/python/framework/test_util.py
เขียนการทดสอบแบบปิดผนึก
การทดสอบทางสุญญากาศไม่จำเป็นต้องมีแหล่งข้อมูลภายนอก พวกเขาเต็มไปด้วยทุกสิ่งที่ต้องการและพวกเขาเพิ่งเริ่มบริการปลอม ๆ ที่พวกเขาอาจต้องการ บริการอื่น ๆ นอกเหนือจากการทดสอบของคุณเป็นแหล่งที่มาของการไม่กำหนดปัจจัย แม้ว่าจะมีบริการอื่น ๆ ถึง 99% แต่เครือข่ายก็สามารถหลุดออกได้การตอบสนอง rpc อาจล่าช้าและคุณอาจพบข้อความแสดงข้อผิดพลาดที่อธิบายไม่ได้ บริการภายนอกอาจเป็นได้ แต่ไม่ จำกัด เพียง GCS, S3 หรือเว็บไซต์ใด ๆ