Google is committed to advancing racial equity for Black communities. See how.

Лучшие практики тестирования TensorFlow

Это рекомендуемые практики для тестирования кода в репозитории TensorFlow .

Прежде, чем вы начнете

Перед тем, как внести свой вклад в исходный код проекта TensorFlow, пожалуйста , просмотрите CONTRIBUTING.md файл в GitHub репо проекта. (Например, см. Файл CONTRIBUTING.md для основного репозитория TensorFlow .) Все участники кода должны подписать лицензионное соглашение участника (CLA).

Общие принципы

Зависит только от того, что вы используете в своих правилах СТРОИТЕЛЬСТВА

TensorFlow - большая библиотека, и в зависимости от полного пакета при написании модульного теста для ее подмодулей была обычной практикой. Однако это отключает bazel зависимостей. Это означает, что системы непрерывной интеграции не могут разумно исключить несвязанные тесты для прогонов до / после отправки. Если вы полагаетесь только на подмодули, которые вы тестируете в своем файле BUILD , вы сэкономите время всех разработчиков TensorFlow и получите много ценных вычислительных мощностей.

Однако изменение зависимости сборки, чтобы исключить полные целевые объекты TF, накладывает некоторые ограничения на то, что вы можете импортировать в свой код Python. Вы больше не сможете использовать import tensorflow as tf оператора import tensorflow as tf в своих модульных тестах. Но это достойный компромисс, поскольку он избавляет всех разработчиков от необходимости запускать тысячи ненужных тестов.

Весь код должен иметь модульные тесты

Для любого кода, который вы пишете, вы должны также написать его модульные тесты. Если вы пишете новый файл foo.py , вы должны поместить его модульные тесты в foo_test.py и отправить его с тем же изменением. Стремитесь к охвату инкрементным тестированием> 90% для всего вашего кода.

Избегайте использования собственных правил тестирования bazel в TF

У TF много тонкостей при запуске тестов. Мы постарались скрыть все эти сложности в наших макросах bazel. Чтобы избежать этого, используйте следующие вместо собственных правил тестирования. Обратите внимание, что все они определены в 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 , используйте вместо py_test правило, определенное в tensorflow.bzl. Вам просто нужно добавить следующую строку вверху файла BUILD: load(“tensorflow/tensorflow.bzl”, “py_test”)

Знайте, где выполняется тест

Когда вы пишете тест, наша тестовая инфраструктура может позаботиться о запуске ваших тестов на CPU, GPU и ускорителях, если вы напишете их соответствующим образом. У нас есть автоматизированные тесты, которые работают в Linux, macos, Windows, в которых есть системы с графическими процессорами или без них. Вам просто нужно выбрать один из макросов, перечисленных выше, а затем использовать теги, чтобы ограничить место их выполнения.

  • manual тег исключит выполнение вашего теста где бы то ни было. Это включает в себя ручное выполнение тестов с использованием таких шаблонов, как bazel test tensorflow/…

  • no_oss исключит выполнение вашего теста в официальной тестовой инфраструктуре TF OSS.

  • no_mac или no_windows могут использоваться для исключения вашего теста из соответствующих наборов тестов операционной системы.

  • Тег no_gpu можно использовать для исключения вашего теста из тестовых наборов графического процессора.

Убедитесь, что тесты выполняются в ожидаемых тестовых наборах

У TF довольно много тестовых наборов. Иногда их установка может сбивать с толку. Могут возникнуть различные проблемы, из-за которых ваши тесты не будут включены в непрерывную сборку. Таким образом, вы должны убедиться, что ваши тесты выполняются должным образом. Сделать это:

  • Подождите, пока ваше предварительное представление запроса на слияние (PR) завершится.
  • Прокрутите вниз свой PR, чтобы увидеть проверки статуса.
  • Щелкните ссылку «Подробности» справа от любого чека Kokoro.
  • Проверьте список «Цели», чтобы найти новые добавленные цели.

У каждого класса / модуля должен быть свой собственный файл модульного теста.

Отдельные тестовые классы помогают нам лучше изолировать сбои и ресурсы. Они приводят к тому, что тестовые файлы намного короче и легче читаются. Следовательно, все ваши файлы Python должны иметь хотя бы один соответствующий тестовый файл (для каждого foo.py он должен иметь foo_test.py ). Для более сложных тестов, таких как интеграционные тесты, требующие различных настроек, можно добавить больше тестовых файлов.

Скорость и время работы

Шардинг следует использовать как можно реже

Вместо сегментирования рассмотрите следующее:

  • Делаем ваши тесты меньше
  • Если это невозможно, разделите тесты на

Шардинг помогает уменьшить общую задержку теста, но того же можно добиться, разбив тесты на более мелкие цели. Разделение тестов дает нам более тонкий уровень контроля над каждым тестом, сводя к минимуму ненужные предварительные запуски и уменьшая потерю покрытия из-за того, что buildcop отключает всю цель из-за неправильного выполнения теста. Более того, сегментирование требует скрытых затрат, которые не столь очевидны, например, запуска всего тестового кода инициализации для всех сегментов. Инфраструктура передала нам эту проблему как источник, создающий дополнительную нагрузку.

Меньшие тесты лучше

Чем быстрее будут выполняться ваши тесты, тем больше вероятность, что люди будут запускать ваши тесты. Одна дополнительная секунда для вашего теста может сэкономить несколько часов дополнительного времени, потраченного на выполнение вашего теста разработчиками и нашей инфраструктурой. Постарайтесь, чтобы ваши тесты длились менее 30 секунд (в неоптимальном режиме!), И сделайте их небольшими. Отметьте свои тесты как средние только в крайнем случае. Инфра не выполняет никаких больших тестов в виде предварительных или пост-представлений! Поэтому пишите большой тест только в том случае, если вы собираетесь организовать, где он будет запускаться. Несколько советов по ускорению выполнения тестов:

  • Выполняйте меньше итераций обучения в своем тесте
  • Рассмотрите возможность использования внедрения зависимостей для замены тяжелых зависимостей тестируемой системы простыми подделками.
  • Рассмотрите возможность использования меньших входных данных в модульных тестах
  • Если ничего не помогает, попробуйте разделить тестовый файл.

Время тестирования должно быть нацелено на половину тайм-аута размера теста, чтобы избежать хлопьев

С тестовыми целями bazel небольшие тесты имеют тайм- bazel 1 минуту. Среднее время ожидания теста составляет 5 минут. Инфраструктура тестирования TensorFlow не выполняет большие тесты. Однако многие тесты не детерминированы по времени, которое они занимают. По разным причинам ваши тесты могут время от времени занимать больше времени. И если вы отметите тест, который выполняется в среднем в течение 50 секунд как маленький, ваш тест будет расслаиваться, если он будет выполняться на машине со старым процессором. Поэтому для небольших тестов стремитесь к средней продолжительности работы 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 в тестах может быть основной причиной нестабильности. Использование спящего режима для ожидания другого потока никогда не будет детерминированным, особенно при использовании нескольких потоков. Это связано с тем, что система не может гарантировать какой-либо порядок выполнения различных потоков или процессов. Поэтому предпочитайте детерминированные конструкции синхронизации, такие как мьютексы.

Проверьте, не шелушится ли тест

Хлопья заставляют строителей и разработчиков терять много часов. Их сложно обнаружить и отладить. Несмотря на то, что существуют автоматизированные системы для обнаружения нестабильности, им необходимо накопить сотни тестовых прогонов, прежде чем они смогут точно зарегистрировать тесты. Даже когда они обнаруживают, они запрещают ваши тесты, и тестовое покрытие теряется. Поэтому авторы тестов должны проверять, являются ли их тесты нестабильными при написании тестов. Это легко сделать, запустив тест с флагом: --runs_per_test=1000

Используйте TensorFlowTestCase

TensorFlowTestCase принимает необходимые меры предосторожности, такие как заполнение всех генераторов случайных чисел, используемых для максимального уменьшения нестабильности. По мере того, как мы обнаруживаем и исправляем больше источников нестабильности, все они будут добавлены в TensorFlowTestCase. Поэтому при написании тестов для тензорного потока следует использовать TensorFlowTestCase. TensorFlowTestCase определяется здесь: tensorflow/python/framework/test_util.py

Напишите герметичные тесты

Для герметичных испытаний не нужны внешние ресурсы. У них есть все необходимое, и они просто запускают любые поддельные сервисы, которые могут им понадобиться. Источниками недетерминизма являются любые сервисы, кроме ваших тестов. Даже при 99% доступности других сервисов сеть может давать сбой, ответ rpc может быть отложен, и вы можете получить необъяснимое сообщение об ошибке. Сторонними службами могут быть, помимо прочего, GCS, S3 или любой веб-сайт.