Обычно мы не слишком много тестируем.Когда-то у нас было правило «80% тестового покрытия», но мы обнаружили, что это не делает нас лучше или быстрее.Большинство кодов и структур данных, которые мы используем, спроектированы достаточно защищенно, поэтому редко бывает вред, который нельзя отменить.Наши пользователи предпочитают быстрое время выполнения работ до 100% времени безотказной работы.
У нас есть два настроенных приложения: my app.appspot.com
и my app-test.appspot.com
.Вся база кода предназначена для того, чтобы app-test.appspot.com
никогда не изменял состояние во внешних системах.
иногда мы копируем данные из app.appspot.com
в app-test.appspot.com
.Это может запутаться, потому что счетчики генерации идентификаторов для хранилища данных не обновляются, но работают достаточно хорошо.
Мы разрабатываем на обеих системах.Разработка внешнего интерфейса в основном выполняется на app.appspot.com
, а эксперименты с бэкендом - на app-test.appspot.com
.
У нас есть три ветви: master, rc и production.rc обновляется с master и production с rc.rc ежедневно развертывается на rc.app.appspot.com или управляет ими.Production еженедельно развертывается на production.app.appspot.com (который также доступен через другое имя приложения.
Разработчики обычно используют dev- whoami
.app.appspot.com для экспериментов. Мы используемсервера разработки очень мало, потому что нам нужно много данных из хранилища данных.
Теперь для тестирования: мы в основном используем приемочные тесты. У нас есть небольшая структура под названием resttest_dsl
, которую мы используем для описания таких тестов:
client.GET('/').responds_access_denied()
client.GET('/', auth='user').responds_html()
client.GET('/admin').responds_access_denied()
client.GET('/admin', auth='user').responds_access_denied()
client.GET('/admin', auth='admin').responds_html()
client.GET('/artikel/').responds_with_html_to_valid_auth()
client.GET('/artikel/?q=Ratzfratz', auth='user').responds_html()
client.GET('/api/ic/v3/a/14600/03/zukunft.json').responds_with_json_to_valid_auth()
client.GET('/kunden/SC50313/o/SO1194829/', auth='user').responds_html()
client.GET('/api/masterdata/artikel/v2/artnr/14600/bild=s210').redirects_to('...')
имя хоста и учетные данные имеют значения по умолчанию, но могут быть перезаписаны переменными окружения. Большинство ошибок, которые мы когда-либо исправляли, имеют регрессионный тест. Мы используем Makefile
s для управления всем этим. Например:
deploy:
appcfg.py update -V dev-`whoami` -A app .
TESTHOST=dev-`whoami`.app.appspot.com make resttest
open http://dev-`whoami`.app.appspot.com/
Развертывание всегда происходит из центрального репозитория git следующим образом:
deploy_production:
rm -Rf tmp
mkdir tmp
(cd tmp ; git clone git@github.com:user/app.git)
(cd tmp/app ; git checkout production ; make dependencies)
(cd tmp/app ; git show-ref --hash=7 refs/remotes/origin/production > version.txt)
appcfg.py update -V "v`cat tmp/app/version.txt`" -A app tmp/app
(cd tmp/huWaWi ; TESTHOST="v`cat version.txt`".app.appspot.com make resttest)
appcfg.py update -V production -A app tmp/app
appcfg.py backends -V production -A app tmp/huWaWi app
Сначала мы развертываем версию, помеченную текущей версией в AppEngine. Затем мы запускаем resttest.py
противэто только что развернутая версия. При сбое m make
останавливает выполнение. Если сбоя не произошло, развертывается «рабочая версия».
Мы также выполняем обязательные проверки pep8 , pyflakes и pylint при проверке исходного кода.
В целом у нас очень простые тестыно запускать их много и против производственного кода и данных.Для нас это отлавливает большую часть ошибок, которые мы совершаем, что относительно мало усилий.