...

понедельник, 30 сентября 2013 г.

[Из песочницы] Автоматизированное создание отчета по тестированию

Введение




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

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

Совсем недавно я столкнулся с Google Script. Это инструмент, позволяющий намного эффективнее работать с документами в облаке. Я решил, что он подойдет для задачи автоматизированного составления отчетов по тестированию. И вот что получилось.
Структура



В документе в виде таблицы я веду описания пользовательских сценариев для тестирования приложений. Не претендую на подробное описание, однако самая критичная информация там имеется, а именно: раздел, к которому относится сценарий, название самого сценария, шаги сценария, статус пройденного сценария, комментарии и ссылка на страницу с описанием ошибке в баг-трекере. Набор статусов у нас обычно ограничен «Реализовано», «Дефект», «Отложено». На некоторых проектах могут добавляться и другие, но не суть. Выглядит это следующим образом:

image


Очевидно, что такие сценарии не удобно вести на одной странице — есть смысл разбить на несколько листов (например, по этапам или релизам).


Задача



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



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

Вот такой вид отчета для сценариев:

image


Вот что получилось для статистики:


image



Как же это делать?



Для начала нам нужно создать скрипт внутри документа. Делается это буквально за несколько минут.

Сначала необходимо создать таблицу на диске Google.

image

Затем перейти в меню «Инструменты» и выбрать пункт «Редактор скриптов»

image


После этого выбираем пункт меню «Пустой проект», стираем код и начинаем писать свой.

Для начала напишем функцию onOpen:



function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{name: 'Сгенерировать отчет по тестированию', functionName: 'generateReport_'}
];
spreadsheet.addMenu('Отчет', menuItems);
}




Это поможет нам добавить пункт меню в панель инструментов:

image

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



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'шника.

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий