Выпуск 12. Февраль 2014

Perl на FOSDEM 2014 | Содержание | Обход дерева директорий на Perl и Haskell (часть 2)

Как настроить сервер для CPAN Testers

В этой статье рассказано о том, как поднять окружение для автоматического тестирования новых модулей из CPAN и отправки отчетов на сайт cpantesters.org

CPAN Testers — сайт, где публикуются результаты автоматических тестов модулей, загружаемых на CPAN. Тесты выполняются под управлением разных операционных систем, на разной архитектуре и под разными версиями перла.

На январь 2014 статистика показывала более ста версий Perl, от 5.3.0 до 5.19.8, и около тридцати типов операционных систем. Разумеется, не все комбинации доступны, а матрица пересечений крайне разрежена. В топе операционных систем находятся Linux (на него приходится максимум вариантов версий перла), OpenBSD, FreeBSD, Solaris, NetBSD, Windows, OS X и Debian. Неудивительно, что основные стабильные версии (5.8, 5.10, 5.12, 5.14 и все следующие четные версии и их подверсии) тестируются наиболее активно.

Такое разнообразие получено практически бесплатно, потому что вся работа по тестированию ведется отдельными энтузиастами на своих компьютерах. (Неплохой пример работающей уже несколько лет распределенной вычислительной системы, созданной на перле.)

Архитектура CPAN Testers и история создания сайта кратко описана в документации к одноименному модулю. Работа над сайтом велась на нескольких QA-хакатонах, проходящих с 2008 года. До 2010 года отчеты о тестировании высылались (в том числе при автоматическом тестировании) по факсу электронной почте, а теперь все отправляется через HTTPS в формате JSON. Отчеты принимает сервер под названием Metabase.

Вступить в ряды тестеров (эпизодических или постоянных) относительно легко. В простейшем случае требуется настроить свою среду таким образом, чтобы при установке или тестировании вами любого модуля (вместе со всеми зависимостями) автоматически отправлялся отчет. На этой основе очень просто построить сервер, который будет круглосуточно загружать и тестировать новые модули, попутно отправляя в метабазу все отчеты.

CPAN Testers рекомендует для установки модулей использовать классический CPAN и CPANPLUS. Именно вокруг них построена вся архитектура генерации и отправки отчетов. Несмотря на то, что сегодня популярнее cpamninus, есть смысл изучить работу CPAN Testers именно на оригинальном модуле CPAN. CPANPLUS я рассматривать не буду, но зато расскажу про то, как тестировать модули с помощью cpanminus — это совсем никак не отражено на вики wiki.cpantesters.org, но с апреля 2013 года Breno G. de Oliveira (garu) разрабатывает утилиту cpanm-reporter, которую, возможно, выберут приверженцы cpanm.

Даже если ваш выбор — cpanm, но вы хотите разобраться в том, как работает вся экосистема CPAN Testers, не переходите сразу к чтению последнего раздела, а изучите сначала работу с CPAN.pm; многое из этого будет использовать и cpanm-reporter.

Создание и отправка отчетов с помощью CPAN.pm

Подготовка

Основная архитектурная идея заключается в том, что вся работа по отчетам тестирования выполняется через хуки в самом CPAN.pm. Требуется лишь установить модули для CPAN Testers, настроить SSL и создать локальный файл профиля для cpantesters.org.

Прежде всего необходимо убедиться, что перл сможет ходить на сайты по HTTPS. Если этого нет, надо поставить Crypt::SSLeay, например, так:

sudo apt-get install libssl-dev
sudo cpan Crypt::SSLeay

(В скобках замечу, что CPAN Testers не против и HTTP, но вряд ли стоит пользоваться такой возможностью.) Если у вас нет поддержки SSL, то при при первой попытке отправить отчет вы получите такую ошибку:

Scheme 'https' is not supported by your LWP::UserAgent.
You must install Crypt::SSLeay or IO::Socket::SSL or use http instead.

Теперь надо установить модуль Task::CPAN::Reporter, вместе с которым поставится и все необходимое для отчетов, их генерации, редактирования и отправки на сервер Metabase:

sudo cpan Task::CPAN::Reporter

Среди прочего установится и модуль Test::Reporter::Transport::Metabase, именно он отвечает за формат отчета и общение сервером metabase.cpantesters.org.

Завершающие шаги подготовки — инициализация CPAN::Reporter и создание своего Metabase-профиля.

Это делается из командной строки cpan (без sudo):

$ cpan
cpan[1]> o conf init test_report

Вам предложат ответить на несколько вопросов:

  • Generate test reports if CPAN::Reporter is installed (yes/no)? (правильный ответ: yes)
  • Would you like me configure CPAN::Reporter now? (yes)

И попросят указать имя и электронный адрес:

  • email_from?

В ответ следует ввести сразу и имя, и PAUSE ID (если он есть), и e-mail (хотя вопрос сформулирован как email_from?, больше никаких вопросов про имя и псевдоним не последует). В моем случае это:

"Andrew Shitov (ANDY)" <andy@shitov.ru>
  • edit_report? (no, хотя вы можете зачем-то ответить yes)
  • send_report? (yes, в этом случае отчет будет отправляться сразу после установки или тестирования модуля, педанты privacy должны быть начеку)

Наконец, последний вопрос — про транспорт. Система построена таким образом, что готовые отчеты могут, например, сохраняться в файл, уходить в /dev/null или отправляться по почте. По умолчанию предлагается самый разумный вариант: отправка на сервер Metabase.

  • transport? [Metabase uri https://metabase.cpantesters.org/api/v1/ id_file metabase_id.json] (просто соглашаемся)

(Если вы заинтересовались возможными способами доставки отчетов, изучите модули Test::Reporter::Transport::*. При отправке в методе send модуля Test::Reporter создается инстанс одного из подклассов:

my $transport_class = "Test::Reporter::Transport::$transport_type"; 

Однако, в документации указано, что этот подход не предназначен для создания своих транспортных модулей-плагинов, а все это планируется делать в неймспейсе CPAN::Testers.)

Наконец, создание профиля:

  • Would you like to run 'metabase-profile' now to create '/home/ash/.cpanreporter/metabase_id.json'? (y)

Все почти настроено, надо сохранить сделанные изменения в файле ~/.cpan/CPAN/MyConfig.pm:

cpan[2]> o conf commit

После этой процедуры будут созданы файлы ~/.cpanreporter/config.ini и ~/.cpanreporter/metabase_id.json.

Файл metabase_id.json рекомендуют положить в отдельный каталог ~/.cpantesters. Его можно перенести из ~/.cpanreporter и поправить путь в строке transport файла ~/.cpanreporter/config.ini:

transport=Metabase uri https://metabase.cpantesters.org/api/v1/ id_file ~/.cpantesters/metabase_id.json

(Не пытайтесь в оболочке cpan в последнем вопросе сразу указывать ~/.cpantesters/metabase_id.json, этот каталог не будет создан, и профиль никуда не запишется.)

Файл профиля metabase_id.json следует копировать на все компьютеры, на которых вы собираетесь выполнять тестирование и отправлять отчеты в метабазу. В документации отдельно указано, что всегда необходимо подписываться одним и тем же именем, независимо от того, откуда вы работаете. Для внесения изменений в профиль существует утилита metabase-profile.

Эксплуатация

Настройка закончена. Теперь любой вызов cpan install или cpan test будет отправлять на CPAN Testers отчеты о модулях и всех зависимостях, которые пришлось поставить.

Например:

cpan test Date::Converter

Среди вывода утилиты cpan для каждого устанавливаемого модуля окажутся такие строки:

CPAN::Reporter: Test result is 'pass', All tests successful.
CPAN::Reporter: preparing a CPAN Testers report for Date-Converter-1.1
CPAN::Reporter: sending test report with 'pass' via Metabase

Убедиться, что отчет получен, можно, заглянув в файл metabase.cpantesters.org/tail/log.txt, который обновляется раз в пять минут и содержит список последних 1000 отчетов. Вот искомая запись:

[2014-01-16T00:22:35Z] [Andrew Shitov (ANDY)] [pass] [ANDY/Date-Converter-1.1.tar.gz] [arm-linux-gnueabihf-thread-multi-64int] [perl-v5.14.2] [4c0d34b6-7e44-12e5-a0c2-f318f6b0b9cd] [2014-01-16T00:22:35Z]

Чтобы не отправлять дубликаты, ведется файл ~/.cpanreporter/reports-sent.db. При повторном тестировании модуля в этом случае появится подобное сообщение:

CPAN::Reporter: this appears to be a duplicate report for the test phase:
PASS Test-utf8-1.00 armv6l-linux 3.6.11+

Test report will not be sent.

Если же отчет все-таки отправился, то его тело будет выглядеть примерно так:

{
  "content": "[{\"content\":\"{\\\"osversion\\\":\\\"3.2.0-4-amd64\\\",
  \\\"textreport\\\":\\\"This distribution has been tested as part of 
  the CPAN Testers .....}]",
  "metadata": {
      "core": {
          "resource": "cpan:///distfile/ANDY/Acme-Test-42-0.1.tar.gz",
          "update_time": "2014-01-15T22:26:51Z",
          "creator": "metabase:user:98903baf-5fc8-3cf9-a47b-0c7b5e930d28",
          "type": "CPAN-Testers-Report",
          "creation_time": "2014-01-15T22:26:51Z",
          "guid": "8879b2e5-9c71-3094-beab-988c20b655f3",
          "schema_version": 1,
          "valid": 1
      }
  }
}

В поле textreport показана только первая строка, в реальности там очень много текста, любопытные могут перенаправить отчет в файл, исправив конфигурацию в ~/.cpanreporter/config.ini или сдампив переменную $metabase_report из модуля Test::Reporter::Transport::Metabase.

Отчеты при установке модулей

В предудущем разделе была продемонстрирована команда cpan test, которая лишь тестировала, но не устанавливала модуль, отправляя при этом отчет. С установкой дело обстоит точно так же, но есть момент, связанный с правами пользователя.

Если вы устанавливаете модуль от имени root (например, используя sudo), то отчеты не создадутся и не отправятся, потому что для этого пользователя нет ни Metabase-профиля, ни правильно сконфигурированного CPAN.pm. Решить эту проблему очень просто: достаточно повторить все процедуры от имени суперпользователя или скопировать соответствующие файлы профиля и конфигурации в папку /root/. После этого отчеты начнут отправляться и при командах типа

sudo cpan install Test::utf8

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

Установка и инициализация:

sudo cpan App::perlbrew
perlbrew init

Установка нужной версии перла:

perlbrew install perl-5.18.2

Запуск оболочки с нужным перлом:

perlbrew switch perl-5.18.2

Если продолжать работать в этой оболочке, то отчеты о тестировании будут создаваться и отправляться как при тестировании, так и при установке модулей:

cpan test Moose
cpan install Moo

Smoke-тестирование на основе CPAN.pm

Теперь все настроено для того, чтобы начать автоматически загружать с CPAN новые модули, тестировать их и отправлять отчеты на CPAN Testers. Это и есть smoke-тестирование.

Для smoke-тестирования можно выделить или отдельный сервер или виртуальную машину. Следует быть осторожным, поскольку модули, попадающие на CPAN, не проверяются антивирусом. Поэтому лучше всего запускать автоматизацию не от имени суперпользователя, а как минимум с помощью perlbrew, тем более что в таком случае появляется возможность тестировать модули с разными версиями перла.

Перед началом работы необходимо установить модуль CPAN::Reporter::Smoker:

cpan CPAN::Reporter::Smoker

Запуск тестов тоже крайне прост:

perl -MCPAN::Reporter::Smoker -e start

Функция start загружает список последних обновлений на CPAN и начинает по очереди тестировать все модули из этого списка. По умолчанию в очередь на тестирование попадают последние сто модулей, но для каждого из них будут протестированы и все зависимости, поэтому не исключено, что фактическое число обработанных модулей окажется на порядок больше.

Загрузка списков модулей и их индексирование могут занять значительное время, после чего программа начинает цикл, в котором выполняется командная строка для тестирования или установки модуля:

# Start smoking
DIST:
for my $d ( 0 .. $#{$dists} ) {
  my $dist = CPAN::Shell->expandany($dists->[$d]);

  ... 
    # invoke CPAN.pm to test distribution
    system($perl, "-MCPAN", "-e",
      "\$CPAN::Config->{test_report} = 1; " . $trust_string
      . $reset_string . ($args{'install'} ? 'install' : 'test')
      . "( '$dists->[$d]' )"
    );

Для каждого модуля формируется и выполняется подобная командная строка:

/usr/bin/perl -MCPAN -e "$CPAN::Config->{test_report} = 1; test( 'SHLOMIF/App-Countdown-v0.4.3.tar.gz' )"

Всю остальную работу ведет модуль CPAN.pm, поэтому если он к этому моменту настроен для работы с Metabase-сервером, то сам по себе будет отправлять отчеты для всех «раскуриваемых» модулей.

Дополнительно имеет смысл попросить CPAN.pm не перепроверять модули, если они уже были протестированы и записаны в историю. Для этого следует установить флаг trust_test_report_history и сохранить его в конфигурации модуля:

$ cpan
cpan[1]> o conf init trust_test_report_history
cpan[2]> o conf commit

Кроме исключительно тестирования возможно сразу устанавливать модули. Для этого требуется передать соответствующий аргумент при вызове функции start:

perl -MCPAN::Reporter::Smoker -e'start(install => 1)'

В любом случае дистрибутивы загруженных модулей сохраняются локально в каталоге ~/.cpan/sources/authors/id, поэтому отсутствие установленного зависимого модуля совместно с проверкой файла ~/.cpanreporter/reports-sent.db почти никак не сказывается на скорости тестирования.

Отключение ожидания ввода

Тесты, входящие в дистрибутивы некоторых модулей, могут запрашивать ввод от пользователя. Чтобы автоматическое тестирование не останавливалось на таких местах, модуль CPAN::Reporter::Smoker устанавливает несколько переменных окружения, поэтому тесты имеют возможность узнать, стоит ли ждать ввода или нет:

# Let things know we're running automated
local $ENV{AUTOMATED_TESTING} = 1;

# Always accept default prompts
local $ENV{PERL_MM_USE_DEFAULT} = 1;
local $ENV{PERL_EXTUTILS_AUTOINSTALL} = "--defaultdeps";

Первая переменная — флаг, сигнализирующий об автоматическом режиме, две других позволяют всегда принимать ответы по умолчанию, не спрашивая человека.

На эту возможность стоит обратить внимание тем, кто создает тесты для своих модулей. Например, модуль Term::Title, позволяющий изменить заголовок окна терминала, во время тестов останавливается и дважды спрашивает пользователя, видит ли он изменения в заголовке:

# Do you see '[Hello]' in the title bar of this window? (y/n)?
y

t/01-Term-Title.t .. 5/8 # Has the title bar been cleared? (y/n)?
y

При автоматическом тестировании это не имеет смысла, поэтому в файле t/01-Term-Title.t выполняется проверка переменной окружения AUTOMATED_TESTING:

SKIP:
{
    skip "Automated testing not supported for tab titles", 2
        if $ENV{AUTOMATED_TESTING};

Создание и отправка отчетов с помощью App::cpanminus

Чтобы отправлять отчеты тестирования для модулей, установленных с помощью cpanm, следует воспользоваться утилитой cpanm-reporter, для установки которой достаточно поставить модуль App::cpanminus::reporter:

sudo cpanm App::cpanminus::reporter

Как и в случае с тестированием через CPAN.pm, для начала работы требуется настройка конфигурации и создание профиля. Команда для инициализации выглядит так:

cpanm-reporter --setup

Если профиль уже был создан для CPAN.pm, то эту команду запускать необязательно, поскольку для для cpanm-reporter будут использоваться те же файлы конфигурации и профиля. В этом случае на все вопросы во время настройки будут предложены ответы, прочитанные из ~/.cpanreporter/config.ini. При отсутствии файла metabase_id.json, где хранится ваш Metabase-профиль, будет предложено запустить утилиту metabase-profile, описанную выше.

Чтобы отправить отчет на CPAN Testers, необходимо сначала обычным способом установить модуль, используя cpanm, а затем запустить утилиту cpanm-reporter:

cpanm Validator-LIVR
cpanm-reporter -v

При запуске без ключа --verbose или -v утилита cpanm-reporter ничего не напечатает, и будет трудно ощутить свою причастноть к полезному делу тестирования модулей.

(cpanm-reporter не ведет reports-sent.db, поэтому при каждом запуске будут отправляться одни и те же отчеты. Чтобы этого избежать, запускайте отправку только после установки модуля, когда cpanm обнуляет файл build.logприм. ред.)

Обратите внимание, что при установке модуля с помощью sudo придется решить те же проблемы с поиском правильных файлов логов, настроек и профилей, что и у CPAN::Reporter.

Важно, чтобы cpan-reporter был вызван как можно раньше после установки модуля. Если этого не сделать в течение получаса, вы получите жалобу на устаревший файл build.log:

Fatal: build.log was created longer than 30 minutes ago.

Если вы уверены, что за это время ничего не могло произойти, смело запускайте репортер с ключем --force:

cpanm-reporter -v --force

Точно так же, как и ранее, успешно загруженные отчеты (вместе с отчетами по модулям, которые пришлось поставить в качестве зависимостей) появляются в логе metabase.cpantesters.org/tail/log.txt.

Андрей Шитов


Perl на FOSDEM 2014 | Содержание | Обход дерева директорий на Perl и Haskell (часть 2)
Нас уже 1381. Больше подписчиков — лучше выпуски!

Комментарии к статье

Чат