Отчётность IBM Rational ClearCase. Часть 3

Источник: developerworks
Рустам Зайдуллин, ведущий инженер, ТатАСУнефть" ОАО "Татнефть" Александр Новичков, руководитель отдела внедрения и консалтинга, СМ-Консалт

Рисунок 6. Диалог ввода даты
Рисунок 6. Диалог ввода даты

Далее таким же образом считываем введённое значение из файла. Затем по выбранному месяцу определяем число дней в месяце

if ($mon eq "january")
{
	$days=@mdays[0]; $imon=1;
}
elsif ($mon eq "february")
{
	$days=@mdays[1]; $imon=2;
}
elsif ($mon eq "march")
{
	$days=@mdays[2]; $imon=3;
}
elsif ($mon eq "april")
{
	$days=@mdays[3]; $imon=4;
}
elsif ($mon eq "may")
{
	$days=@mdays[4]; $imon=5;
}
elsif ($mon eq "june")
{
	$days=@mdays[5]; $imon=6;
}
elsif ($mon eq "july")
{
	$days=@mdays[6]; $imon=7;
}
elsif ($mon eq "august")
{
	$days=@mdays[7]; $imon=8;
}
elsif ($mon eq "september")
{
	$days=@mdays[8]; $imon=9;
}
elsif ($mon eq "october")
{
	$days=@mdays[9]; $imon=10;
}
elsif ($mon eq "november")
{
	$days=@mdays[10]; $imon=11;
}
elsif ($mon eq "december")
{
	$days=@mdays[11]; $imon=12;
};

После этого запрашиваем день отчётного периода. Если ранее были введены текущие год и месяц, ограничиваем список текущим днём.

if (($year == $cyear) && ($imon == $cmon))
{
	for ($d = 1; $d < $cday+1; $d++)
	{
		$dayso="$dayso,$d";
	};
	$dayso=substr($dayso,1,length($dayso));
}
else
{
	for ($d = 1; $d < $days+1; $d++)
	{
		$dayso="$dayso,$d";
	};
	$dayso=substr($dayso,1,length($dayso));
};

Форма этого диалога выглядит следующим образом (рисунок 7).

Рисунок 7. Диалог ввода даты
Рисунок 7. Диалог ввода даты

После считывания из файла введённого значения дня начала отчётного периода формируем строки даты. Одну из них создаём со словесным обозначением месяца (например, "april""), другую - с числовым (соответственно, "4"). Далее пригодятся оба варианта.

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

Рисунок 8. Контекстное меню ClearCase с внесёнными дополнениями
Рисунок 8. Контекстное меню ClearCase с внесёнными дополнениями

Настройки пункта "Отчёт по группе интеграции" контекстного меню приведены на рисунке 9. По второму аргументу - "integr" - скрипт определит имя файла со списком персоналий.

Рисунок 9. Настройка контекстного меню
Рисунок 9. Настройка контекстного меню

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

$otdel = $ARGV[1];
$path = "\\\\clearcase\\addins\\context_menu\\reports\\";
$file=$path.$otdel.".txt";

open(FL, $file) // die "Can't open file \n";
$i=0;

while (<FL>) 
{
@users[$i]=split(FL);
$i=$i+1;
};
close FL;

Теперь вся информация для поиска версий подготовлена, и остаётся выполнить запрос, получить выборку нужных версий и рассчитать для них метрики. Для расчета метрик мы используем бесплатно распространяемую утилиту cccc.exe. Чтобы получить метрики по исходному коду, необходимо запустить утилиту с путём к файлу, содержащему исходный код. В нашем случае это будет путь к версии элемента версионного хранилища.

Остаётся выполнить еще одно подготовительное действие. Так как результат мы хотим получить в таблицу MS Excel, нужно инициировать для этого новую книгу.

Добавим библиотеки работы с OLE-объектами и с объектами MS-Excel в заголовок скрипта.

use Win32;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Excel';

Ловим открытое приложение MS Excel, если таковое имеется, в противном случае создаём новое. Создаём новую книгу:

$Excel = Win32::OLE->GetActiveObject('Excel.Application') 
				// Win32::OLE->new('Excel.Application'); 
$Excel->{Visible} = 1;

$Book = $Excel->Workbooks->Add;
$Sheet = $Book->Worksheets(1);

Запишем в файл заголовок - название отчёта, и шапку формируемой таблицы

$Sheet->Range("A1")->{Value} = "Отчёт за период с $idato по $cdato в каталоге $where";
$Sheet->Range("A2")->{Value} = "Разработчик";
$Sheet->Range("B2")->{Value} = "Версия файла";
$Sheet->Range("C2")->{Value} = "LOC";
$Sheet->Range("D2")->{Value} = "MVG";
$Sheet->Range("F2")->{Value} = "L_C";
$row=2;

Далее описана процедура, которая ищет по заданным критериям версии и рассчитывает для них метрики. Здесь мы должны сделать небольшое отступление, так как на этом этапе возникает вопрос обработки файлов формата XML. Скрипт, который мы пишем, будет выполняться встроенным в ClearCase языком Perl - ccperl. В поставку ccperl не включены распространённые библиотеки для обработки XML - XML::SAX и XML::Parser. Данные модули являются свободно распространяемыми, найти их можно на сайте CPAN. Там же находятся инструкции по установке дополнительных модулей, сведения о зависимых модулях и вся необходимая информация. Но при установке дополнительных модулей в ccperl возникают проблемы. Можно использовать обычный Perl, но в этом случае возникает необходимость установки его на все рабочие станции, на которых будет выполняться скрипт. Другой вариант - самостоятельно описать анализ XML-файла в скрипте, который, собственно, по своему содержанию является обычным текстовым файлом. В данном примере мы поступим именно таким образом.

Для начала проанализируем файл с исходным кодом и посмотрим, что, собственно, выдаст нам утилита. Для этого выбираем файл, и выполняем строку cccc.exe <путь_к_файлу>. Для того чтобы не запускать используемую утилиту без указания полного пути к ней, мы прописали этот путь в переменную среды окружения PATH. Утилита формирует несколько файлов, но нас интересует файл с именем анализируемого файла и расширением XML. Нас интересуют также следующие метрики: число строк кода (LOC), метрика цикломатической сложности по Мак-Кейбу для всей программы (MVG) и метрика качества комментирования программы - отношение числа строк кода к числу строк комментариев (L_C). Ниже приведён фрагмент полученного XML-файла, упомянутые метрики выделены маркером.

1.	<?xml version="1.0" encoding="utf-8"?>
2.	<!--Detailed report on module BackingBean-->
3.	<CCCC_Project>
4.	<module_summary>
5.	<lines_of_code value="425" level="0" />
6.	<lines_of_code_per_member_function value="******" level="0" />
7.	<McCabes_cyclomatic_complexity value="18" level="0" />
8.	<McCabes_cyclomatic_complexity_per_member_function value="******" level="2" />
9.	<lines_of_code value="112" level="0" />
10.	<lines_of_code_per_member_function value="********" level="2" />
11.	<lines_of_code_per_line_of_comment value="3.795" level="0" />
12.	<McCabes_cyclomatic_complexity_per_line_of_comment value="0.161" level="0" />
13.	<weighted_methods_per_class_unity value="13" level="0" />
14.	<weighted_methods_per_class_visibility value="0" level="0" />
15.	<depth_of_inheritance_tree value="0" level="0" />
16.	<number_of_children value="0" level="0" />
17.	<coupling_between_objects value="8" level="0" />
18.	<IF4 value="0" level="0" />
19.	<IF4_per_member_function value="********" level="0" />
20.	<IF4_visible value="0" level="0" />
21.	<IF4_visible_per_member_function value="********" level="0" />
22.	<IF4_concrete value="0" level="0" />
23.	<IF4_concrete_per_member_function value="********" level="0" />
24.	</module_summary>

Теперь мы можем описать правила для выборки значений метрик скриптом. Выше мы сформировали массив с именами разработчиков, работающих в версионном хранилище. Теперь выполняем поиск созданных каждым разработчиком версий, для каждой найденной версии выполняем расчет выбранных метрик. Далее описан цикл, обрабатывающий значения массива, вызов процедуры расчёта метрик и, естественно, сама процедура.

foreach $user (@users)
{
	chop($user);
	$row++;
	$Sheet->Range("A$row")->{Value} = $user;
	DoCommand("cleartool find . -name \"*.java\" -version 
			\"created_since(25-march-2007)&& created_by($user)\" -print");
	$row++;
};

Мы записали в таблицу имя разработчика и выполняем поиск в выбранном каталоге версионного хранилища ClearCase версий, созданных данным специалистом в течение указанного срока. Поиск выполняется описанной ниже процедурой, она же анализирует полученный результат и записывает его в созданную книгу MS Excel.

sub DoCommand
{
my $cmd = shift;
$count=0;

my $line;
open(CMD, "$cmd 2>&1 /");
foreach $line (<CMD>)

Мы выполнили поиск, и перехватываем результат из консоли в переменную $line. Обрабатываем полученное значение:

		{
		chop($line);
		$end = substr ($line, length($line)-2, length($line));
		if ($end ne "\\0")

Проверяем окончание строки. Мы не будем учитывать нулевые версии, так как они не содержат информации. Остальные версии подвергаются анализу.

		{
			$tmpname = substr ($line, 0, index($line, "@@"));

В переменной $tmpname мы сформировали стандартное имя файла, т.е. завершающееся расширением. Используемая в примере утилита расчета метрик не может оперировать названиями файлов, содержащими полный путь ClearCase, т.е. названиями версий.

			system("cleartool co -unr -nc -version $line ");
			system ("cccc.exe \"$tmpname\" 
					 --xml_outfile=c:\\temp\\cccc\\tmp.xml 
					--outdir=c:\\temp\\cccc");

Мы выполнили операцию CheckOut для обрабатываемой версии, чтобы увидеть её в текущем представлении ClearCase, и вычисляем метрики. Операция CheckOut выполняется без резервирования версии - на тот случай, если в настоящее время кто-то работает с данным элементом. Результат сохраняется во временном файле c:\temp\cccc\tmp.xls

		open(FL, "c:\\temp\\cccc\\tmp.xml") // die "Can't open file \n";
			$i=1;
			while (<FL>) 
			{
				@lines[$i]=split(FL);
				$i=$i+1;
			};
			close FL;

Содержимое файла считано в массив построчно. Далее, находим в нужных нам строках значения метрик (см. выше).

		$LOC=substr(@lines[5],index(@lines[5],"=\"")+2,index(@lines[5],"\"
				 level")-index(@lines[5],"=\"")-1);
		$MVG=substr(@lines[7],index(@lines[7],"=\"")+2,index(@lines[7],"\"
				 level")-index(@lines[7],"=\"")-1);
		$L_C=substr(@lines[11],index(@lines[11],"=\"")+2,index(@lines[11],"\"
				 level")-index(@lines[11],"=\"")-1);

Значения метрик записаны в переменные, и нам остаётся только сохранить полученные результаты в таблицу. Записываем название версии (здесь - полное имя, включая номер версии) и вычисленные метрики.

		$Sheet->Range("B$row")->{Value} = $line;
		$Sheet->Range("C$row")->{Value} = $LOC;
		$Sheet->Range("D$row")->{Value} = $MVG;
		$Sheet->Range("E$row")->{Value} = $L_C;

Далее отменяем CheckOut, создаём на версии атрибуты, содержащие соответствующие значения метрик и добавляем приращение к переменной указателя строки таблицы.

		system("cleartool unco -rm $line ");
		system("cleartool mkattr LOC $LOC \"$line \"");
		system("cleartool mkattr MVG $MVG \"$line \"");
		system("cleartool mkattr L_C $L_C \"$line \"");
$row++;
	};
}
close CMD;
}

Результат работы скрипта представлен в таблице 1. После завершения работы скрипта книга MS Excel остаётся открытой для дальнейшей работы. Можно настроить сохранение сформированной таблицы и рассылку по электронной почте - как угодно, в зависимости от потребностей.

Таблица 1. Результат работы скрипта

Разработчик Версия файла LOC MVG L_C
pavel .\controller\BackingBean.java@@\main\dev\12 428 16 3.927
.\controller\BackingBean.java@@\main\dev\11 439 19 3.658
.\controller\BackingBean.java@@\main\dev\10 439 19 3.658
.\controller\BackingBean.java@@\main\dev\9 435 19 3.884
.\controller\BackingBean.java@@\main\dev\8 435 19 3.884
.\controller\BackingBean.java@@\main\dev\7 425 18 3.795
.\controller\Mail.java@@\main\dev\4 338 37 5.541
.\controller\Mail.java@@\main\dev\3 320 37 5.246
.\controller\Mail.java@@\main\dev\2 316 36 5.097
.\controller\Mail.java@@\main\dev\1 314 36 4.906
.\controller\MenuSearch.java@@\main\dev\3 109 18 5.737
andrey .\controller\ShuttleAuthCheck.java@@\main\dev\4 93 11 3.207
.\controller\ShuttleAuthCheck.java@@\main\dev\3 93 11 3.207
.\controller\ShuttleAuthCheck.java@@\main\dev\2 94 11 3.357
.\model\KEntity.java@@\main\dev\2 205 33 8.542
.\ProcessThread.java@@\main\dev\6 49 1 3.500
.\ProcessThread.java@@\main\dev\5 48 1 16.000
.\servlet\Crystal.java@@\main\dev\5 545 31 3.893
.\servlet\Crystal.java@@\main\dev\4 545 31 3.865
.\servlet\Crystal.java@@\main\dev\3 535 29 3.794
.\servlet\SecurityFilter.java@@\main\dev\9 65 10 9.286
.\servlet\SecurityFilter.java@@\main\dev\8 65 10 9.286

Читать часть 4


Страница сайта http://185.71.96.61
Оригинал находится по адресу http://185.71.96.61/home.asp?artId=22836