Тестирование и диагностика
Операторы диагностики
DESCRIBE
Возвращает схему отношения.
Синтаксис
| DESCRIBE alias; |
Термины
| alias | Имя отношения. |
Использование
Используйте оператор DESCRIBE для просмотра схемы отношения. Вы можете просмотреть внешние отношения, а также отношения, определенные в операторе FOREACH вложенного уровня.
Пример
В этом примере схема задается с помощью предложения AS. Если все данные соответствуют схеме, Pig будет использовать назначенные типы.
A = LOAD 'student' AS (name:chararray, age:int, gpa:float);
B = FILTER A BY name matches 'J.+';
C = GROUP B BY name;
D = FOREACH C GENERATE COUNT(B.age);
DESCRIBE A;
A: {name: chararray,age: int,gpa: float}
DESCRIBE B;
B: {name: chararray,age: int,gpa: float}
DESCRIBE C;
C: {group: chararray,B: {(name: chararray,age: int,gpa: float)}}
DESCRIBE D;
D: {long}
В этом примере схема не задана. Все поля по умолчанию имеют тип bytearray или long (см. Типы данных).
a = LOAD 'student';
b = FILTER a BY $0 matches 'J.+';
c = GROUP b BY $0;
d = FOREACH c GENERATE COUNT(b.$1);
DESCRIBE a;
Schema for a unknown.
DESCRIBE b;
2008-12-05 01:17:15,316 [main] WARN org.apache.pig.PigServer - bytearray is implicitly cast to chararray under LORegexp Operator
Schema for b unknown.
DESCRIBE c;
2008-12-05 01:17:23,343 [main] WARN org.apache.pig.PigServer - bytearray is implicitly caste to chararray under LORegexp Operator
c: {group: bytearray,b: {null}}
DESCRIBE d;
2008-12-05 03:04:30,076 [main] WARN org.apache.pig.PigServer - bytearray is implicitly caste to chararray under LORegexp Operator
d: {long}
Этот пример показывает, как просмотреть схему вложенного отношения с помощью оператора ::.
A = LOAD 'studentab10k' AS (name, age, gpa);
B = GROUP A BY name;
C = FOREACH B {
D = DISTINCT A.age;
GENERATE COUNT(D), group;}
DESCRIBE C::D;
D: {age: bytearray}
DUMP
Выводит результаты на экран.
Синтаксис
| DUMP alias; |
Термины
| alias | Имя отношения. |
Использование
Используйте оператор DUMP для выполнения (выполнения) операторов Pig Latin и вывода результатов на экран. DUMP предназначен для интерактивного режима; операторы выполняются немедленно, и результаты не сохраняются. Вы можете использовать DUMP как средство отладки, чтобы убедиться, что генерируются ожидаемые результаты.
Обратите внимание, что сценарии производства НЕ должны использовать DUMP, так как это отключит оптимизации многократных запросов и, вероятно, замедлит выполнение (см. Сохранение против вывода).
Пример
В этом примере выполняется вывод после каждого оператора.
A = LOAD 'student' AS (name:chararray, age:int, gpa:float); DUMP A; (John,18,4.0F) (Mary,19,3.7F) (Bill,20,3.9F) (Joe,22,3.8F) (Jill,20,4.0F) B = FILTER A BY name matches 'J.+'; DUMP B; (John,18,4.0F) (Joe,22,3.8F) (Jill,20,4.0F)
EXPLAIN
Отображает планы выполнения.
Синтаксис
| EXPLAIN [–script pigscript] [–out path] [–brief] [–dot] [-xml] [–param param_name = param_value] [–param_file file_name] alias; |
Термины
| –script | Используйте для указания сценария Pig. |
| –out | Используйте для указания выходного пути (каталога). Сгенерирует файл logical_plan[.txt|.dot], physical_plan[.text|.dot], exec_plan[.text|.dot] в указанном пути. По умолчанию (если путь не указан): Stdout |
| –brief | Не расширять вложенные планы (представление меньшей схемы для обзора). |
| –dot, -xml | Текстовый режим (по умолчанию): разделенный вывод будет разделен на разделы. Режим Dot: выводит формат, который можно передать в утилиту dot для графического отображения — сгенерирует направленный ациклический граф (DAG) планов в любом поддерживаемом формате (.gif, .jpg...). Режим Xml: выводит xml, который представляет план (в настоящее время показан только логический план). |
| –param param_name = param_value | |
| –param_file file_name | |
| alias | Имя отношения. |
Использование
Используйте оператор EXPLAIN для просмотра логических, физических и планов выполнения MapReduce, используемых для вычисления указанного отношения.
Если сценарий не указан:
-
Логический план показывает цепочку операторов для выполнения, чтобы построить отношение. Также применяются проверка типов и независимые от бэкенда оптимизации (например, применение фильтров на ранней стадии).
-
Физический план показывает, как логические операторы преобразуются в физические операторы, специфичные для бэкенда. Также применяются некоторые оптимизации бэкенда.
-
План MapReduce показывает, как физические операторы группируются в задания MapReduce.
Если указан сценарий без алиаса, выводится вся диаграмма выполнения (логическая, физическая или MapReduce).
Если указан сценарий с алиасом, выводится план для данного алиаса.
Пример
В этом примере оператор EXPLAIN генерирует все три плана. (Обратите внимание, что в этом примере показана только часть вывода.)
A = LOAD 'student' AS (name:chararray, age:int, gpa:float);
B = GROUP A BY name;
C = FOREACH B GENERATE COUNT(A.age);
EXPLAIN C;
-----------------------------------------------
Logical Plan:
-----------------------------------------------
Store xxx-Fri Dec 05 19:42:29 UTC 2008-23 Schema: {long} Type: Unknown
|
|---ForEach xxx-Fri Dec 05 19:42:29 UTC 2008-15 Schema: {long} Type: bag
etc ...
-----------------------------------------------
Physical Plan:
-----------------------------------------------
Store(fakefile:org.apache.pig.builtin.PigStorage) - xxx-Fri Dec 05 19:42:29 UTC 2008-40
|
|---New For Each(false)[bag] - xxx-Fri Dec 05 19:42:29 UTC 2008-39
| |
| POUserFunc(org.apache.pig.builtin.COUNT)[long] - xxx-Fri Dec 05
etc ...
--------------------------------------------------
| Map Reduce Plan
-------------------------------------------------
MapReduce node xxx-Fri Dec 05 19:42:29 UTC 2008-41
Map Plan
Local Rearrange[tuple]{chararray}(false) - xxx-Fri Dec 05 19:42:29 UTC 2008-34
| |
| Project[chararray][0] - xxx-Fri Dec 05 19:42:29 UTC 2008-35
etc ...
ILLUSTRATE
Отображает пошаговое выполнение последовательности операторов.
Синтаксис
| ILLUSTRATE {alias | -script scriptfile}; |
Термины
| alias | Имя отношения. |
| -script scriptfile | Ключевое слово script, за которым следует имя сценария Pig (например, myscript.pig). Файл сценария не должен содержать оператор ILLUSTRATE. |
Использование
Используйте оператор ILLUSTRATE, чтобы просмотреть, как данные преобразуются посредством последовательности операторов Pig Latin. ILLUSTRATE позволяет тестировать программы на небольших наборах данных и получить более быструю обратную связь.
ILLUSTRATE основан на генераторе примеров (см. Generating Example Data for Dataflow Programs). Алгоритм работает путем извлечения небольшой выборки входных данных и последующей передачи этих данных через конвейер. Однако некоторые операторы, такие как JOIN и FILTER, могут исключать кортежи из данных — и это может привести к отсутствию данных, следующих через конвейер. Для решения этой проблемы алгоритм автоматически генерирует примеры данных практически в реальном времени. Таким образом, вы можете увидеть распространение данных через конвейер, которые не были найдены в исходных входных данных, но эти данные ничего не изменяют и гарантируют, что вы сможете изучить семантику ваших операторов Pig Latin.
Как показано в примерах ниже, вы можете использовать ILLUSTRATE для просмотра отношения или всего сценария Pig.
Пример — Отношение
Этот пример демонстрирует использование ILLUSTRATE с отношением. Обратите внимание, что оператор LOAD должен включать схему (предложение AS).
grunt> visits = LOAD 'visits.txt' AS (user:chararray, url:chararray, timestamp:chararray);
grunt> DUMP visits;
(Amy,yahoo.com,19990421)
(Fred,harvard.edu,19991104)
(Amy,cnn.com,20070218)
(Frank,nba.com,20070305)
(Fred,berkeley.edu,20071204)
(Fred,stanford.edu,20071206)
grunt> recent_visits = FILTER visits BY timestamp >= '20071201';
grunt> user_visits = GROUP recent_visits BY user;
grunt> num_user_visits = FOREACH user_visits GENERATE group, COUNT(recent_visits);
grunt> DUMP num_user_visits;
(Fred,2)
grunt> ILLUSTRATE num_user_visits;
------------------------------------------------------------------------
| visits | user: chararray | url: chararray | timestamp: chararray |
------------------------------------------------------------------------
| | Fred | berkeley.edu | 20071204 |
| | Fred | stanford.edu | 20071206 |
| | Frank | nba.com | 20070305 |
------------------------------------------------------------------------
-------------------------------------------------------------------------------
| recent_visits | user: chararray | url: chararray | timestamp: chararray |
-------------------------------------------------------------------------------
| | Fred | berkeley.edu | 20071204 |
| | Fred | stanford.edu | 20071206 |
-------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------
| user_visits | group: chararray | recent_visits: bag({user: chararray,url: chararray,timestamp: chararray}) |
------------------------------------------------------------------------------------------------------------------
| | Fred | {(Fred, berkeley.edu, 20071204), (Fred, stanford.edu, 20071206)} |
------------------------------------------------------------------------------------------------------------------
--------------------------------------------------
| num_user_visits | group: chararray | long |
--------------------------------------------------
| | Fred | 2 |
--------------------------------------------------
Пример — Сценарий
Этот пример демонстрирует использование ILLUSTRATE со сценарием Pig. Обратите внимание, что сам сценарий не должен содержать оператор ILLUSTRATE.
grunt> cat visits.txt Amy yahoo.com 19990421 Fred harvard.edu 19991104 Amy cnn.com 20070218 Frank nba.com 20070305 Fred berkeley.edu 20071204 Fred stanford.edu 20071206 grunt> cat visits.pig visits = LOAD 'visits.txt' AS (user, url, timestamp); recent_visits = FILTER visits BY timestamp >= '20071201'; historical_visits = FILTER visits BY timestamp <= '20000101'; DUMP recent_visits; DUMP historical_visits; STORE recent_visits INTO 'recent'; STORE historical_visits INTO 'historical'; grunt> exec visits.pig (Fred,berkeley.edu,20071204) (Fred,stanford.edu,20071206) (Amy,yahoo.com,19990421) (Fred,harvard.edu,19991104) grunt> illustrate -script visits.pig ------------------------------------------------------------------------ | visits | user: bytearray | url: bytearray | timestamp: bytearray | ------------------------------------------------------------------------ | | Amy | yahoo.com | 19990421 | | | Fred | stanford.edu | 20071206 | ------------------------------------------------------------------------ ------------------------------------------------------------------------------- | recent_visits | user: bytearray | url: bytearray | timestamp: bytearray | ------------------------------------------------------------------------------- | | Fred | stanford.edu | 20071206 | ------------------------------------------------------------------------------- --------------------------------------------------------------------------------------- | Store : recent_visits | user: bytearray | url: bytearray | timestamp: bytearray | --------------------------------------------------------------------------------------- | | Fred | stanford.edu | 20071206 | --------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------- | historical_visits | user: bytearray | url: bytearray | timestamp: bytearray | ----------------------------------------------------------------------------------- | | Amy | yahoo.com | 19990421 | ----------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- | Store : historical_visits | user: bytearray | url: bytearray | timestamp: bytearray | ------------------------------------------------------------------------------------------- | | Amy | yahoo.com | 19990421 | -------------------------------------------------------------------------------------------
Сценарии Pig и идентификаторы заданий MapReduce
Сложные сценарии Pig часто генерируют множество заданий MapReduce. Чтобы помочь в отладке сценария, Pig выводит сводку выполнения, которая показывает, какие отношения (алиасы) сопоставляются с каждым заданием MapReduce.
JobId Maps Reduces MaxMapTime MinMapTIme AvgMapTime MaxReduceTime
MinReduceTime AvgReduceTime Alias Feature Outputs
job_201004271216_12712 1 1 3 3 3 12 12 12 B,C GROUP_BY,COMBINER
job_201004271216_12713 1 1 3 3 3 12 12 12 D SAMPLER
job_201004271216_12714 1 1 3 3 3 12 12 12 D ORDER_BY,COMBINER
hdfs://mymachine.com:9020/tmp/temp743703298/tmp-2019944040,
Статистика Pig
Pig Statistics — это фреймворк для сбора и хранения статистических данных на уровне скриптов для Pig Latin. Характеристики скриптов Pig Latin и полученных задач MapReduce собираются во время выполнения скрипта. Эти статистические данные затем доступны для пользователей Pig и инструментов, использующих Pig (таких как Oozie), для получения после завершения задачи.
Новые статистические данные Pig и существующие статистические данные Hadoop также можно получить через файл истории задач Hadoop (и файл xml задачи). Piggybank содержит HadoopJobHistoryLoader, который служит примером использования самого Pig для запроса этих статистических данных (загрузчик может быть использован как реализация эталона, но НЕ поддерживается для использования в производстве).
Java API
Несколько новых общедоступных классов упрощают интеграцию внешних инструментов, таких как Oozie, со статистикой Pig.
Статистические данные Pig доступны здесь: http://pig.apache.org/docs/r0.9.0/api/
Классы статистики находятся в пакете: org.apache.pig.tools.pigstats
- PigStats
- JobStats
- OutputStats
- InputStats
Класс PigRunner имитирует поведение класса Main, но возвращает пользователю объект статистики. По желанию, вы можете вызвать API с реализацией обработчика прогресса, который будет вызываться runtime Pig во время выполнения.
package org.apache.pig;
public abstract class PigRunner {
public static PigStats run(String[] args, PigProgressNotificationListener listener)
}
public interface PigProgressNotificationListener extends java.util.EventListener {
// just before the launch of MR jobs for the script
public void LaunchStartedNotification(int numJobsToLaunch);
// number of jobs submitted in a batch
public void jobsSubmittedNotification(int numJobsSubmitted);
// a job is started
public void jobStartedNotification(String assignedJobId);
// a job is completed successfully
public void jobFinishedNotification(JobStats jobStats);
// a job is failed
public void jobFailedNotification(JobStats jobStats);
// a user output is completed successfully
public void outputCompletedNotification(OutputStats outputStats);
// updates the progress as percentage
public void progressUpdatedNotification(int progress);
// the script execution is done
public void launchCompletedNotification(int numJobsSucceeded);
}
Файл XML задачи
В конфигурации задачи включены следующие записи:
| Статистика Pig | Описание |
| pig.script.id | UUID скрипта. Все задачи, запущенные скриптом, имеют один и тот же идентификатор скрипта. |
| pig.script | Текст скрипта в кодировке base64. |
| pig.command.line | Командная строка, используемая для запуска скрипта. |
| pig.hadoop.version | Установка Hadoop. |
| pig.version | Используемая версия Pig. |
| pig.input.dirs | Список входных каталогов для задачи, разделённые запятыми. |
| pig.map.output.dirs | Список выходных каталогов в фазе map задачи, разделённые запятыми. |
| pig.reduce.output.dirs | Список выходных каталогов в фазе reduce задачи, разделённые запятыми. |
| pig.parent.jobid | Список идентификаторов родительских задач, разделённые запятыми. |
| pig.script.features | Список функций Pig, используемых в скрипте. |
| pig.job.feature | Список функций Pig, используемых в задаче. |
| pig.alias | Псевдоним, связанный с задачей. |
Загрузчик истории задач Hadoop
HadoopJobHistoryLoader в Piggybank загружает файлы истории задач Hadoop и файлы xml задач из файловой системы. Для каждой задачи MapReduce загрузчик генерирует кортеж со схемой (j:map[], m:map[], r:map[]). Первый map в схеме содержит записи, связанные с задачей. Вот некоторые важные имена ключей в map:
| PIG_SCRIPT_ID CLUSTER QUEUE_NAME JOBID JOBNAME STATUS | USER HADOOP_VERSION PIG_VERSION PIG_JOB_FEATURE PIG_JOB_ALIAS PIG_JOB_PARENTS | SUBMIT_TIME LAUNCH_TIME FINISH_TIME TOTAL_MAPS TOTAL_REDUCES |
Примеры использования загрузчика для запроса статистических данных Pig показаны ниже.
Примеры
Найти скрипты, которые генерируют более трёх задач MapReduce:
a = load '/mapred/history/done' using HadoopJobHistoryLoader() as (j:map[], m:map[], r:map[]); b = group a by (j#'PIG_SCRIPT_ID', j#'USER', j#'JOBNAME'); c = foreach b generate group.$1, group.$2, COUNT(a); d = filter c by $2 > 3; dump d;
Найти время выполнения каждого скрипта (в секундах):
a = load '/mapred/history/done' using HadoopJobHistoryLoader() as (j:map[], m:map[], r:map[]);
b = foreach a generate j#'PIG_SCRIPT_ID' as id, j#'USER' as user, j#'JOBNAME' as script_name,
(Long) j#'SUBMIT_TIME' as start, (Long) j#'FINISH_TIME' as end;
c = group b by (id, user, script_name)
d = foreach c generate group.user, group.script_name, (MAX(b.end) - MIN(b.start)/1000;
dump d;
Найти количество скриптов, запущенных пользователем и очередью на кластере:
a = load '/mapred/history/done' using HadoopJobHistoryLoader() as (j:map[], m:map[], r:map[]); b = foreach a generate j#'PIG_SCRIPT_ID' as id, j#'USER' as user, j#'QUEUE_NAME' as queue; c = group b by (id, user, queue) parallel 10; d = foreach c generate group.user, group.queue, COUNT(b); dump d;
Найти скрипты, у которых есть неудачные задачи:
a = load '/mapred/history/done' using HadoopJobHistoryLoader() as (j:map[], m:map[], r:map[]); b = foreach a generate (Chararray) j#'STATUS' as status, j#'PIG_SCRIPT_ID' as id, j#'USER' as user, j#'JOBNAME' as script_name, j#'JOBID' as job; c = filter b by status != 'SUCCESS'; dump c;
Найти скрипты, которые используют только стандартное распараллеливание:
a = load '/mapred/history/done' using HadoopJobHistoryLoader() as (j:map[], m:map[], r:map[]); b = foreach a generate j#'PIG_SCRIPT_ID' as id, j#'USER' as user, j#'JOBNAME' as script_name, (Long) r#'NUMBER_REDUCES' as reduces; c = group b by (id, user, script_name) parallel 10; d = foreach c generate group.user, group.script_name, MAX(b.reduces) as max_reduces; e = filter d by max_reduces == 1; dump e;
Обработчик уведомлений о прогрессе Pig
Pig предоставляет возможность регистрации обработчика для получения уведомлений о событиях во время выполнения скрипта. События включают создание плана MapReduce, запуск скрипта, прогресс скрипта, завершение скрипта, отправка задачи, начало задачи, завершение задачи и неудача задачи.
Для регистрации обработчика необходимо установить параметр pig.notification.listener с полным квалифицированным именем реализации org.apache.pig.tools.pigstats.PigProgressNotificationListener. Класс должен существовать в классе пути процесса, отправляющего задачу Pig. Если установлен параметр pig.notification.listener.arg, значение будет передано в конструктор реализующего класса, который принимает один строковый параметр.
PigUnit
PigUnit — это простой фреймворк xUnit, который позволяет легко тестировать ваши скрипты Pig. С помощью PigUnit можно выполнять модульное тестирование, регрессионное тестирование и быстрое прототипирование. Если вы запускаете Pig в локальном режиме, настройка кластера не требуется.
Сборка PigUnit
Для компиляции PigUnit выполните показанную ниже команду из Pig trunk. Компиляция создаст файл pigunit.jar.
$pig_trunk ant pigunit-jar
Запуск PigUnit
Вы можете запустить PigUnit, используя локальный режим Pig или режим mapreduce.
Локальный режим
PigUnit запускается в локальном режиме Pig по умолчанию. Локальный режим быстрый и позволяет использовать вашу локальную файловую систему в качестве кластера HDFS. Локальный режим не требует реального кластера, но новый локальный кластер создаётся каждый раз.
Режим mapreduce
PigUnit также работает в режиме mapreduce Pig. Режим mapreduce требует использования кластера Hadoop и установки HDFS. Он активируется, когда системная переменная Java pigunit.exectype.cluster установлена в любое значение: например, -Dpigunit.exectype.cluster=true или System.getProperties().setProperty("pigunit.exectype.cluster", "true"). Выбранный кластер должен быть указан в CLASSPATH (аналогично переменной HADOOP_CONF_DIR).
Пример PigUnit
Многие примеры PigUnit доступны в тестах PigUnit.
Приведённый здесь пример вычисляет топ N наиболее частых запросов. Скрипт Pig top_queries.pig похож на скрипт Популярность фраз запроса в руководстве по Pig. Он ожидает в качестве входных данных файл запросов и параметр n (n равен 2 в нашем случае для вычисления топ 2).
Настройка теста для этого скрипта проста, поскольку аргумент и входные данные задаются двумя текстовыми массивами. То же самое касается ожидаемого результата скрипта, который будет сравниваться с фактическим результатом выполнения скрипта Pig.
Тест Java
@Test
public void testTop2Queries() {
String[] args = {
"n=2",
};
PigTest test = new PigTest("top_queries.pig", args);
String[] input = {
"yahoo",
"yahoo",
"yahoo",
"twitter",
"facebook",
"facebook",
"linkedin",
};
String[] output = {
"(yahoo,3)",
"(facebook,2)",
};
test.assertOutput("data", input, "queries_limit", output);
}
top_queries.pig
data =
LOAD 'input'
AS (query:CHARARRAY);
queries_group =
GROUP data
BY query;
queries_count =
FOREACH queries_group
GENERATE
group AS query,
COUNT(data) AS total;
queries_ordered =
ORDER queries_count
BY total DESC, query;
queries_limit =
LIMIT queries_ordered $n;
STORE queries_limit INTO 'output';
Запуск
Тест можно выполнить с помощью JUnit (или любого другого фреймворка для Java тестирования). Для этого требуется:
- pig.jar
- pigunit.jar
Тест занимает около 25 секунд для выполнения и должен пройти успешно. В случае ошибки (например, изменение параметра n на n=3), будет показана разница в выходных данных:
junit.framework.ComparisonFailure: null expected:<...ahoo,3)
(facebook,2)[]> but was:<...ahoo,3)
(facebook,2)[
(linkedin,1)]>
at junit.framework.Assert.assertEquals(Assert.java:81)
at junit.framework.Assert.assertEquals(Assert.java:87)
at org.apache.pig.pigunit.PigTest.assertEquals(PigTest.java:272)
Советы по устранению неполадок
Ниже обсуждаются распространённые проблемы, которые могут возникнуть.
Путь к классам в режиме mapreduce
При использовании PigUnit в режиме mapreduce убедитесь, что $HADOOP_CONF_DIR кластера включён в ваш CLASSPATH.
MiniCluster генерирует его в build/classes.
org.apache.pig.backend.executionengine.ExecException: ERROR 4010: Cannot find hadoop configurations in classpath (neither hadoop-site.xml nor core-site.xml was found in the classpath). If you plan to use local mode, please put -x local option in command line
Не найдены jar-файлы UDF
Эта ошибка означает, что в вашей тестовой среде отсутствуют некоторые jar-файлы.
WARN util.JarManager: Couldn't find the jar for org.apache.pig.piggybank.evaluation.string.LOWER, skip it
Хранение данных
В настоящее время Pig отбрасывает все команды STORE и DUMP. Вы можете указать PigUnit сохранить эти команды и выполнить скрипт:
test = new PigTest(PIG_SCRIPT, args);
test.unoverride("STORE");
test.runScript();
Архив кэша
Для работы с архивом кэша ваша тестовая среда должна иметь опции архива кэша, указанные в переменных Java или в дополнительной XML-конфигурации в её CLASSPATH.
Если вы используете локальный кластер, вам необходимо установить необходимые переменные среды перед его запуском:
export LD_LIBRARY_PATH=/home/path/to/lib
Планируемые улучшения
Улучшения и другие компоненты на основе PigUnit, которые могут быть разработаны позже.
Например, мы могли бы разработать PigTestCase и PigTestSuite поверх PigTest для:
- Добавления понятия рабочих пространств для каждого теста.
- Удаления повторяющегося кода, появляющегося при наличии более одного метода тестирования.
- Добавления автономной утилиты, которая считывает конфигурации тестов и генерирует отчёт о результатах тестов.
© 2007–2016 Apache Software Foundation
Licensed under the Apache Software License version 2.0.
https://pig.apache.org/docs/r0.13.0/test.html