Введение
Так уж сложилось, что у нас в компании ведется учет работ по тестированию в небезызвестных GoogleDocs. Поскольку таким учетом занимаюсь я один, то это идеальный вариант. Плюс еще есть возможность без труда поделиться с наработками с коллегами и не нужно заботиться об актуальности версий — все сохраняется моментально.
Это основные причины выбранного варианта работы. Но, как известно, у любой монеты две стороны. Минус такого подхода состоит в том, что большие проекты трудно обрабатывать и составлять вменяемые отчеты по тестированию (для этих целей, безусловно, подходят системы управления тестами).
Совсем недавно я столкнулся с Google Script. Это инструмент, позволяющий намного эффективнее работать с документами в облаке. Я решил, что он подойдет для задачи автоматизированного составления отчетов по тестированию. И вот что получилось.
Структура
В документе в виде таблицы я веду описания пользовательских сценариев для тестирования приложений. Не претендую на подробное описание, однако самая критичная информация там имеется, а именно: раздел, к которому относится сценарий, название самого сценария, шаги сценария, статус пройденного сценария, комментарии и ссылка на страницу с описанием ошибке в баг-трекере. Набор статусов у нас обычно ограничен «Реализовано», «Дефект», «Отложено». На некоторых проектах могут добавляться и другие, но не суть. Выглядит это следующим образом:
Очевидно, что такие сценарии не удобно вести на одной странице — есть смысл разбить на несколько листов (например, по этапам или релизам).
Задача
Необходимо максимально упростить жизнь тестировщика при составлении отчетов тестирования. Идеальным будет вариант, где можно посмотреть сводку по разделам и проекту целиком, а так же не только получить список ошибок и ссылки на них, но и посмотреть на общую картину.
Решение
В качестве решения я выбрал таблицу, разделенную по разделам. Каждая строка соответствует сценарию тестирования и окрашена в соответствующий цвет (для дефектов — красный, для готовых задач — зеленый, для остального — желтый). При этом подводится статистика для каждого из разделов отдельно (сколько ошибок, сколько успешных сценариев, сколько других, то же самое в процентах) и для всего проекта целиком.
Вот такой вид отчета для сценариев:
Вот что получилось для статистики:
Как же это делать?
Для начала нам нужно создать скрипт внутри документа. Делается это буквально за несколько минут.
Сначала необходимо создать таблицу на диске Google.
Затем перейти в меню «Инструменты» и выбрать пункт «Редактор скриптов»
После этого выбираем пункт меню «Пустой проект», стираем код и начинаем писать свой.
Для начала напишем функцию onOpen:
function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{name: 'Сгенерировать отчет по тестированию', functionName: 'generateReport_'}
];
spreadsheet.addMenu('Отчет', menuItems);
}
Это поможет нам добавить пункт меню в панель инструментов:
Далее пишем функцию, которая будет вызываться при выборе этого пункта меню:
function generateReport_() {
//Список интересующих колонок на странице сценариев
var columns = ['Раздел', 'Название сценария', 'Статус', 'Комментарии', 'Тикет'];
//Список колонок для страницы отчета
var reportColumns = ['Название сценария', 'Статус', 'Комментарии', 'Тикет'];
//Функция для формирования массива с информацией о сценариях
var Data = getAllCases(columns);
//Функция создания листа с отчетом
CreateNewSheet();
//Функция сбора и вывода статистики
var stat = FormReport(Data, reportColumns);
ShowStat(stat);
}
Ну а теперь по порядку.
Функция пробегает по всем листам открытого файла и считывает всю информацию для отчета:
function getAllCases(columns)
{
var sheets = SpreadsheetApp.getActive().getSheets();
var data = new Array();
for (q=0; q<sheets.length; q++)
{
SpreadsheetApp.getActive().setActiveSheet(sheets[q]);
data.push(getCases(columns));
}
return data;
}
Функция формирует массив для вывода в удобочитабельном виде. Тут есть одна особенность — если вы поменяли местами поля на разных листах, то ничего страшного не случится. Массив parts содержит списки разделов, по которым сгруппированы сценарии, а его элементы — имя раздела и список сценариев в виде массива:
function getCases(columns)
{
var range = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var fields = FindFields(range[0], columns);
var parts = new Array();
for (i=1; i<range.length; i++)
{
if (range[i][fields[0]] != '')
{
parts.push(new Array());
parts[parts.length-1]['name'] = range[i][fields[0]];
parts[parts.length-1]['scen'] = new Array();
}
if (range[i][fields[1]] != '')
{
var title = range[i][fields[1]];
}
if (range[i][fields[2]] != '')
{
var scen = new Array();
scen.push(title);
for (j=2; j<fields.length; j++)
{
scen.push(range[i][fields[j]]);
}
parts[parts.length-1]['scen'].push(scen);
}
}
return parts;
}
Собственно, это и есть функция, благодаря которой не так страшно путать местами колонки на страницах сценариев:
function FindFields (data, columns)
{
var fields = new Array();
for (i=0; i<columns.length; i++)
{
for (j=0; j<data.length; j++)
{
if (columns[i] == data[j])
fields.push(j);
}
}
return fields;
}
Для создания нового листа с отчетом:
function CreateNewSheet()
{
SpreadsheetApp.getActive().insertSheet('Отчет');
SpreadsheetApp.setActiveSheet(SpreadsheetApp.getActive().getSheetByName('Отчет'));
}
Формирование самого отчета, сбор статистики и немного оформления:
function FormReport(data, columns)
{
var doc = SpreadsheetApp.getActive();
var stat = [0, 0, 0, 0];
doc.appendRow(columns);
doc.setColumnWidth(1, 300);
doc.setColumnWidth(2, 200);
doc.setColumnWidth(3, 300);
doc.setColumnWidth(4, 300);
for (i=0; i<data.length; i++)
{
for (j=0; j<data[i].length; j++)
{
var temp = WritePart(data[i][j], columns);
stat[0] += +temp[0];
stat[1] += +temp[1];
stat[2] += +temp[2];
stat[3] += +temp[3];
}
}
return stat;
}
Функция вывода в отчет информации по одному разделу и формирование статистики по нему, а так же оформления для более приятного чтения:
function WritePart(data, columns)
{
SpreadsheetApp.getActive().appendRow([data['name']]).set;
var line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("A"+line).setFontSize(20);
var defects = 0;
var done = 0;
var skipped = 0;
var other = 0;
for (k=0; k<data['scen'].length; k++)
{
SpreadsheetApp.getActive().appendRow(data['scen'][k]);
var line = SpreadsheetApp.getActive().getLastRow();
switch (data['scen'][k][1])
{
case 'Дефект': defects++; SpreadsheetApp.getActive().getRange("A"+line+":D"+line).setBackground('red'); break;
case 'Реализовано': done++; SpreadsheetApp.getActive().getRange("A"+line+":D"+line).setBackground('green'); break;
case 'Отложено': skipped++; SpreadsheetApp.getActive().getRange("A"+line+":D"+line).setBackground('yellow'); break;
default: other++; SpreadsheetApp.getActive().getRange("A"+line+":D"+line).setBackground('yellow');
}
}
SpreadsheetApp.getActive().appendRow(['', 'Итого по разделу:']);
SpreadsheetApp.getActive().appendRow(['', 'Реализовано:', done, (done/(done+defects+skipped+other)*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("B"+line+":D"+line).setBackground('green');
SpreadsheetApp.getActive().appendRow(['', 'Дефектов:', defects, (defects/(done+defects+skipped+other)*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("B"+line+":D"+line).setBackground('red');
SpreadsheetApp.getActive().appendRow(['', 'Отложено:', skipped, (skipped/(done+defects+skipped+other)*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("B"+line+":D"+line).setBackground('yellow');
SpreadsheetApp.getActive().appendRow(['', 'Другое:', other, (other/(done+defects+skipped+other)*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("B"+line+":D"+line).setBackground('yellow');
var stat = [defects, done, skipped, other];
return stat;
}
И, наконец, финальная статистика и много оформления:
function ShowStat(stat)
{
SpreadsheetApp.getActive().appendRow(['Всего по проекту:']);
var line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("A"+line).setFontSize(20);
SpreadsheetApp.getActive().appendRow(['Реализовано:', stat[1], (stat[1]/(stat[0]+stat[1]+stat[2]+stat[3])*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("A"+line+":C"+line).setBackground('green');
SpreadsheetApp.getActive().appendRow(['Дефектов:', stat[0], (stat[0]/(stat[0]+stat[1]+stat[2]+stat[3])*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("A"+line+":C"+line).setBackground('red');
SpreadsheetApp.getActive().appendRow(['Отложено:', stat[2], (stat[2]/(stat[0]+stat[1]+stat[2]+stat[3])*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("A"+line+":C"+line).setBackground('yellow');
SpreadsheetApp.getActive().appendRow(['Другое:', stat[3], (stat[3]/(stat[0]+stat[1]+stat[2]+stat[3])*100).toFixed(2) + "%"]);
line = SpreadsheetApp.getActive().getLastRow();
SpreadsheetApp.getActive().getRange("A"+line+":C"+line).setBackground('yellow');
}
Для полноценной сборки нужны все эти функции в любой последовательности в файле скрипта.
Код не идеален — есть над чем работать, однако если кому-то это пригодится, буду рад ответить на вопросы.
Заключение
Я привел один из примеров использования скриптов от Google. Стоит признать, что это довольно мощный инструмент для работы с документами. По крайней мере, он хорошо справился с этой задачей. Есть еще примеры использования скриптов для помощи в работе, например, вот эта интересная статья. Судя по всему, Google Script может стать отличным помощником в повседневной жизни IT'шника.
Автор: orlovrs