Praktik terbaik pengujian TensorFlow

Ini adalah praktik yang disarankan untuk menguji kode di repositori TensorFlow .

Sebelum Anda memulai

Sebelum Anda menyumbangkan kode sumber ke proyek TensorFlow, harap tinjau file CONTRIBUTING.md di repo GitHub proyek tersebut. (Misalnya, lihat file CONTRIBUTING.md untuk repo inti TensorFlow .) Semua kontributor kode diharuskan menandatangani Perjanjian Lisensi Kontributor (CLA).

Prinsip umum

Hanya bergantung pada apa yang Anda gunakan dalam aturan BUILD Anda

TensorFlow adalah perpustakaan besar, dan bergantung pada paket lengkap saat menulis pengujian unit untuk submodulnya sudah menjadi praktik umum. Namun, ini menonaktifkan analisis berbasis ketergantungan bazel . Ini berarti bahwa sistem integrasi berkelanjutan tidak dapat dengan cerdas menghilangkan pengujian yang tidak terkait untuk proses pra-pengiriman/pasca-pengiriman. Jika Anda hanya bergantung pada submodul yang Anda uji di file BUILD , Anda akan menghemat waktu untuk semua developer TensorFlow, dan banyak daya komputasi yang berharga.

Namun, memodifikasi ketergantungan build Anda untuk menghilangkan target TF penuh membawa beberapa batasan pada apa yang dapat Anda impor dalam kode Python Anda. Anda tidak akan dapat lagi menggunakan pernyataan import tensorflow as tf dalam pengujian unit Anda. Tapi ini adalah pengorbanan yang berharga karena ini menyelamatkan semua pengembang dari menjalankan ribuan pengujian yang tidak perlu.

Semua kode harus memiliki pengujian unit

Untuk kode apa pun yang Anda tulis, Anda juga harus menulis pengujian unitnya. Jika Anda menulis file baru foo.py , Anda harus menempatkan pengujian unitnya di foo_test.py dan mengirimkannya dalam perubahan yang sama. Targetkan >90% cakupan pengujian tambahan untuk semua kode Anda.

Hindari penggunaan aturan pengujian bazel asli di TF

TF memiliki banyak kehalusan saat menjalankan tes. Kami telah berupaya menyembunyikan semua kerumitan tersebut di makro bazel kami. Untuk menghindari masalah tersebut, gunakan aturan pengujian berikut ini daripada aturan pengujian asli. Perhatikan bahwa semua ini didefinisikan dalam tensorflow/tensorflow.bzl Untuk pengujian CC, gunakan tf_cc_test , tf_gpu_cc_test , tf_gpu_only_cc_test . Untuk pengujian python, gunakan tf_py_test atau gpu_py_test . Jika Anda memerlukan sesuatu yang sangat mirip dengan aturan py_test asli, harap gunakan aturan yang ditentukan di tensorflow.bzl sebagai gantinya. Anda hanya perlu menambahkan baris berikut di bagian atas file BUILD: load(“tensorflow/tensorflow.bzl”, “py_test”)

Waspadai di mana pengujian dijalankan

Saat Anda menulis pengujian, infra pengujian kami dapat menjalankan pengujian Anda pada CPU, GPU, dan akselerator jika Anda menulisnya sesuai dengan itu. Kami memiliki pengujian otomatis yang berjalan di Linux, macOS, windows, yang memiliki sistem dengan atau tanpa GPU. Anda hanya perlu memilih salah satu makro yang tercantum di atas, lalu menggunakan tag untuk membatasi tempat eksekusinya.

  • tag manual akan mengecualikan pengujian Anda agar tidak berjalan di mana pun. Ini termasuk eksekusi pengujian manual yang menggunakan pola seperti bazel test tensorflow/…

  • no_oss akan mengecualikan pengujian Anda agar tidak berjalan di infrastruktur pengujian resmi TF OSS.

  • Tag no_mac atau no_windows dapat digunakan untuk mengecualikan pengujian Anda dari rangkaian pengujian sistem operasi yang relevan.

  • Tag no_gpu dapat digunakan untuk mengecualikan pengujian Anda agar tidak berjalan di rangkaian pengujian GPU.

Verifikasi pengujian yang dijalankan di rangkaian pengujian yang diharapkan

TF memiliki beberapa rangkaian pengujian. Terkadang, pengaturannya mungkin membingungkan. Mungkin ada masalah berbeda yang menyebabkan pengujian Anda dihilangkan dari build berkelanjutan. Oleh karena itu, Anda harus memverifikasi bahwa pengujian Anda dijalankan seperti yang diharapkan. Untuk melakukan ini:

  • Tunggu hingga pra-pengiriman pada Pull Request (PR) Anda berjalan hingga selesai.
  • Gulir ke bagian bawah PR Anda untuk melihat pemeriksaan status.
  • Klik tautan “Detail” di sisi kanan cek Kokoro mana pun.
  • Periksa daftar “Target” untuk menemukan target yang baru Anda tambahkan.

Setiap kelas/unit harus memiliki file pengujian unitnya sendiri

Kelas pengujian terpisah membantu kami mengisolasi kegagalan dan sumber daya dengan lebih baik. Mereka menghasilkan file pengujian yang jauh lebih pendek dan lebih mudah dibaca. Oleh karena itu, semua file Python Anda harus memiliki setidaknya satu file pengujian yang sesuai (Untuk setiap foo.py , harus ada foo_test.py ). Untuk pengujian yang lebih rumit, seperti pengujian integrasi yang memerlukan pengaturan berbeda, boleh saja menambahkan lebih banyak file pengujian.

Kecepatan dan waktu berjalan

Sharding harus digunakan sesedikit mungkin

Daripada melakukan sharding, harap pertimbangkan:

  • Membuat tes Anda lebih kecil
  • Jika hal di atas tidak memungkinkan, pisahkan pengujiannya

Sharding membantu mengurangi latensi pengujian secara keseluruhan, namun hal yang sama dapat dicapai dengan memecah pengujian menjadi target yang lebih kecil. Pemisahan pengujian memberi kami tingkat kontrol yang lebih baik pada setiap pengujian, meminimalkan proses pra-pengiriman yang tidak perlu, dan mengurangi hilangnya cakupan dari buildcop yang menonaktifkan seluruh target karena kasus pengujian yang tidak berfungsi. Selain itu, sharding menimbulkan biaya tersembunyi yang tidak begitu jelas, seperti menjalankan semua kode inisialisasi pengujian untuk semua shard. Masalah ini telah disampaikan kepada kami oleh tim infra sebagai sumber yang menimbulkan beban tambahan.

Tes yang lebih kecil lebih baik

Semakin cepat pengujian Anda dijalankan, semakin besar kemungkinan orang akan menjalankan pengujian Anda. Satu detik ekstra untuk pengujian Anda dapat terakumulasi menjadi berjam-jam waktu ekstra yang dihabiskan untuk menjalankan pengujian Anda oleh pengembang dan infrastruktur kami. Cobalah untuk membuat pengujian Anda berjalan kurang dari 30 detik (dalam mode non-opt!), dan buat pengujian menjadi kecil. Hanya tandai tes Anda sebagai tes sedang sebagai upaya terakhir. Infra tidak menjalankan pengujian besar apa pun sebagai pra-pengiriman atau pasca-pengiriman! Oleh karena itu, tulislah tes berukuran besar hanya jika Anda ingin mengatur di mana tes tersebut akan dijalankan. Beberapa tip untuk membuat pengujian berjalan lebih cepat:

  • Jalankan lebih sedikit iterasi pelatihan dalam pengujian Anda
  • Pertimbangkan untuk menggunakan injeksi ketergantungan untuk menggantikan ketergantungan berat pada sistem yang sedang diuji dengan yang palsu.
  • Pertimbangkan untuk menggunakan data masukan yang lebih kecil dalam pengujian unit
  • Jika tidak ada yang berhasil, coba pisahkan file pengujian Anda.

Waktu pengujian harus mencapai setengah dari waktu tunggu ukuran pengujian untuk menghindari serpihan

Dengan target pengujian bazel , pengujian kecil memiliki batas waktu 1 menit. Batas waktu tes sedang adalah 5 menit. Pengujian besar tidak dijalankan oleh infra pengujian TensorFlow. Namun, banyak tes yang tidak bersifat deterministik dalam jumlah waktu yang dibutuhkan. Karena berbagai alasan, pengujian Anda mungkin memerlukan waktu lebih lama dari waktu ke waktu. Dan, jika Anda menandai pengujian yang berjalan rata-rata selama 50 detik sebagai pengujian kecil, pengujian Anda akan gagal jika dijadwalkan pada mesin dengan CPU lama. Oleh karena itu, targetkan waktu berjalan rata-rata 30 detik untuk pengujian kecil. Targetkan waktu berjalan rata-rata 2 menit 30 detik untuk tes sedang.

Kurangi jumlah sampel dan tingkatkan toleransi untuk pelatihan

Tes yang berjalan lambat menghalangi kontributor. Menjalankan pelatihan dalam ujian bisa sangat lambat. Pilih toleransi yang lebih tinggi agar dapat menggunakan lebih sedikit sampel dalam pengujian Anda agar pengujian Anda tetap cukup cepat (maksimal 2,5 menit).

Hilangkan non-determinisme dan kesalahan

Tulis tes deterministik

Tes unit harus selalu bersifat deterministik. Semua pengujian yang dijalankan pada TAP dan gitar harus dijalankan dengan cara yang sama setiap saat, jika tidak ada perubahan kode yang mempengaruhinya. Untuk memastikan hal ini, berikut adalah beberapa hal yang perlu dipertimbangkan.

Selalu benihkan sumber stokastisitas apa pun

Generator angka acak apa pun, atau sumber stokastisitas lainnya dapat menyebabkan kelemahan. Oleh karena itu, masing-masing harus diunggulkan. Selain membuat pengujian tidak terlalu rumit, hal ini juga membuat semua pengujian dapat direproduksi. Berbagai cara untuk menetapkan beberapa benih yang mungkin perlu Anda atur dalam pengujian TF adalah:

# 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)

Hindari menggunakan sleep dalam pengujian multithread

Menggunakan fungsi sleep dalam pengujian dapat menjadi penyebab utama kelemahan. Terutama ketika menggunakan banyak thread, menggunakan sleep untuk menunggu thread lain tidak akan pernah bersifat deterministik. Hal ini disebabkan sistem tidak dapat menjamin urutan eksekusi thread atau proses yang berbeda. Oleh karena itu, lebih memilih konstruksi sinkronisasi deterministik seperti mutex.

Periksa apakah tesnya terkelupas

Serpihan menyebabkan polisi bangunan dan pengembang kehilangan waktu berjam-jam. Mereka sulit dideteksi dan sulit di-debug. Meskipun ada sistem otomatis untuk mendeteksi kelemahan, sistem tersebut perlu mengumpulkan ratusan pengujian yang dijalankan sebelum dapat secara akurat memasukkan pengujian ke dalam daftar yang ditolak. Bahkan ketika mereka mendeteksi, mereka menolak tes Anda dan cakupan tes hilang. Oleh karena itu, penulis tes harus memeriksa apakah tes mereka tidak stabil saat menulis tes. Hal ini dapat dilakukan dengan mudah dengan menjalankan pengujian Anda dengan flag: --runs_per_test=1000

Gunakan TensorFlowTestCase

TensorFlowTestCase mengambil tindakan pencegahan yang diperlukan seperti menyemai semua generator nomor acak yang digunakan untuk mengurangi kelemahan sebanyak mungkin. Saat kami menemukan dan memperbaiki lebih banyak sumber kelemahan, semua sumber ini akan ditambahkan ke TensorFlowTestCase. Oleh karena itu, Anda harus menggunakan TensorFlowTestCase saat menulis pengujian untuk Tensorflow. TensorFlowTestCase didefinisikan di sini: tensorflow/python/framework/test_util.py

Tulis tes kedap udara

Tes hermetik tidak memerlukan sumber daya dari luar. Mereka penuh dengan semua yang mereka butuhkan, dan mereka hanya memulai layanan palsu apa pun yang mungkin mereka perlukan. Layanan apa pun selain pengujian Anda adalah sumber non determinisme. Bahkan dengan 99% ketersediaan layanan lain, jaringan dapat mengalami gangguan, respons rpc dapat tertunda, dan Anda mungkin mendapatkan pesan kesalahan yang tidak dapat dijelaskan. Layanan luar mungkin, namun tidak terbatas pada, GCS, S3 atau situs web apa pun.