| Автор: Максим Уваров Сейчас очень актуальна проблема тестирования. Все больше и больше                фирм работают по схеме, так называемого, экстремального программирования.                Важной основой данного решения является тестирование. Результаты                тестирования очень важны, но как сделать их более эффективными?                Об этом и пойдет речь в этой статье. Предполагается, что у вас есть набор тестов, которые представляют                собой программу, выводящую слово PASS, если тест прошел или слово                FAIL, если тест не прошел. Приведем пример теста, который выполняется:  #!/bin/bashecho "Simple test"
 echo "1"
 echo "2"
 echo "3"
 echo "PASS: LTT-05 test passed"
 Или теста которые не выполняется:  #!/bin/bashecho "Simple test"\
 echo "1"
 echo "2"
 echo "3"
 echo "FAIL: LTT-06 test failed"
 Для начала нам потребуется где-нибудь хранить статистику о поведенных                тестах. Воспользуемся SQL базой данных mysql. База будет содержать                примерно следующий вид: 1. время проведения теста2. название тестируемой программы
 3. номер теста
 4. статус PASS - если тест прошел. и FAIL - если тест не прошел.
 5. релиз статус
 При разборе данной таблицы можно вывести следующие результаты: 1. Время, занимаемое тестированием данной программы.2. Определить трудные тесты, которые чаще всего не проходят.
 3. Определить вероятность прохождения тестов.
 4. Определить скорость запуска тестов (количество пройденных или                не пройденных тестов, например за день).
 Сменим пароль для пользователя базы  mysqladmin -u root password 'aa' Создадим базу следующим образом:  mysqladmin -p create rtest (если нужно удалить базу с текущим именем, можно воспользоваться                командой mysqladmin -p drop >rtest)Присоединимся к базе
  mysql -u root -p rtest Создадим пользователя, который будет работать с базой  mysql> INSERT INTO user (Host, User,                Password, Select_priv, Insert_priv, Update_priv, Delete_priv)VALUES ('%', 'bob', password('mypass'), 'Y', 'Y', 'Y', 'Y')
 Создадим таблицу:  mysql> CREATE TABLE qastat(time                CHAR(50) NOT NULL,
 testname                CHAR(50) NOT NULL,
 testnum                CHAR(10) NOT NULL,
 status                ENUM('PASS', 'FAIL'),
 realise                INT);
 Если realise = 1, то тестируется релизный продукт.Добавлять данные в таблицу будем следующим образом:
 INSERT INTO qastat( time, testname, testnum,                status, realise)VALUES                ('c_time', 'c_name', 'c_num', 'c_status', 'c_realise')
 Для считывания данных, используем следующий синтаксис:  SELECT testname, testnum, status FROM                qastat Теперь с помощью Python или любого другого языка, но в данном случае                я использую именно Python, мы будем заполнять данную таблицу. Делается это так:  import MySQLdb;def sqlinsert(time, testname, testnum, status, realise):
 query                = 'INSERT INTO qastat(time, testname, testnum, status, realise)                VALUES (\'' + time + '\', \'' \+ testname + '\', \'' + testnum +                '\', \'' + status + '\', \'' + realise + '\')';
 print                query;
 mysql                = MySQLdb.Connection('localhost', 'root', 'aa', 'rtest');
 cursor                = mysql.cursor();
 cursor.execute(query);
 mysql.close();
 return
 Соединяемся с базой через модуль MySQLdb. В котором, в свою очередь,                создается обьект mysql от метода Connection. В модуле работа с базой                данный осуществляется через курсоры, по этому создается курсор cursor                и уже через него мы получаем доступ к базе. Создадим скрипт, который будет разбирать лог от запускаемого теста.                После разбора лога, скрипт будет вносить изменения в таблицу sql.                При чем не важно прошел тест или нет. Скрипт будет считывать название                теста из командной строки, и запускать его.  #!/usr/bin/pythonimport os,sys, time, string , re
 import MySQLdb;
 def sqlinsert(time, testname, testnum, status, realise):
 query                = 'INSERT INTO qastat(time, testname, testnum, status, realise)                VALUES (\'' + time + '\', \'' \+ testname + '\', \'' + testnum +                '\', \'' + status + '\', \'' + realise + '\')';
 print                query;
 mysql                = MySQLdb.Connection('localhost', 'root', 'aa', 'rtest');
 cursor                = mysql.cursor();
 cursor.execute(query);
 mysql.close();
 return
 
 #set up realis
 realise = 0
 test_pass = 0
 test_fail = 0
 #Название запускаемового теста будет передаваться из командной                строки(f_in, f_out) = os.popen2(sys.argv[1:],                'b')
 a = f_out.readlines()
 f_in.close()
 f_out.close()
 
 #find test result
 for x in a:
 print                x
 res                = re.search("PASS: [A-Z]+-[0-9]* test passed",x)
 if(res):
 res                = string.split(x, " ")[1]
 res                = string.split(res,"-")
 testnum                = res[-1]
 testname                = str(res[0])
 test_pass                = 1
 res                = re.search("FAIL: [A-Z]+-[0-9]* test failed",x)
 if(res):
 res                = string.split(x, " ")[1]
 res                = string.split(res,"-")
 testnum                = res[-1]
 testname                = str(res[0])
 test_fail                = 1
 
 print "testnum = %s" % testnum
 print "testname = %s" % testname
 
 result = "UNKNOWN"
 if (test_pass):
 result                = "PASS"
 if (test_fail):
 result                = "FAIL"
 
 print "result = %s" % (result)
 #get date#Логируем в базу дату в формате: год месяц день час минута секунда
  tm = time.localtime()date = "%.2d%.2d%.2d%.2d%.2d%.2d"                % tm[:6]
 date = str(date)
 print "date = %s" % (date)
 
 print "realise = %s" % realise
 
 #insert values to sql database
 sqlinsert(date, testname, str(testnum), result, str(realise))
 В результате выполнения мы видим, что тест прошел и его результат                внесен в базу данных:  debianm:/home/test/py# ./insert.py ./ltt-05.sh  Simple test1
 2
 3
 PASS: LTT-05 test passed
  testnum = 05testname = LTT
 result = PASS
 date = 20041207000048
 realise = 0
 INSERT INTO qastat(time, testname, testnum, status, realise)                VALUES ('20041207000048', 'LTT', '05', 'PASS', '0')
 Теперь нужно считать данную информацию и попытаться сделать из                нее выводы. В данном случае воспользуемся библиотекой matplotlib                (matplotlib.sf.net) которая предоставляет хорошие возможности для                отрисовки различных графиков и диаграмм. Для этого будем использовать следующую программу.  #!/usr/bin/pythonimport MySQLdb;
 import re
 from matplotlib.matlab import *
 # Функция sqlselect использует в качестве акгумента запрос к базе                дынных query# и по умолчанию возвращает всю таблицу целиком.
  def sqlselect(query = 'SELECT * FROM                qastat'):mysql                = MySQLdb.Connection('localhost', 'root', 'aa', 'rtest')
 cursor                = mysql.cursor()
 cursor.execute(query)
 result                = cursor.fetchall()
 mysql.close()
 return                result
 #Данная функция, используя matplotlib, рисует диаграмму относительно#переданных ей аргументов
  def drawchart(Values):ind                = arange(len(Values))
 width                = 1 # the width of the bars
 p1                = bar( style='font-size: 9.0pt;'>ind , Values, width, color='y')
 ylabel('Values')
 title('Title')
 xticks(                ind +width, ind )
 savefig('barchart')
 show()
 return
 Допустим изначально значение таблицы sql равно: ('101101022004', 'LTT', '01', 'PASS', 1L)('1111111111202', 'LTT', '02', 'PASS', 0L)
 ('1111111111202', 'LTT', '02', 'PASS', 0L)
 ('1111111111202', 'LTT', '02', 'PASS', 0L)
 ('1111111111202', 'LTT', '02', 'PASS', 0L)
 ('20041201004050', 'LTT', '06', 'FAIL', 0L)
 ('20041201004126', 'LTT', '06', 'FAIL', 0L)
 ('20041207000048', 'LTT', '05', 'PASS', 0L)
 ('20041207005605', 'LTT', '01', 'PASS', 0L)
 ('20041207005616', 'LTT', '02', 'PASS', 0L)
 ('20041207005622', 'LTT', '03', 'PASS', 0L)
 ('20041207005628', 'LTT', '04', 'PASS', 0L)
 ('20041207005639', 'LTT', '04', 'PASS', 0L)
 
 Тогда на bartchart.png (Рисунок 1) можно увидеть, что 2 тест является                самым успешным (5 успешных запусков и ни одного не успешного.) Тест                номер 6 является самым не успешным тестом (ни одного успешного теста                и 2 теста провалено). #main # Данная функция просто подсчитывает число строк, возвращенное после                запроса sqlselect()
 # Если входные параметры не заданы то будет возвращено общее число                строк. С помощью данной
 # функции можно легко посчитать количество тестов заданных по определенному                имени, дате или
 # номеру, лишь передав функции требуемый sql запрос.
  def countrow():rownum                = 0
 for                row in sqlselect():
 rownum                = rownum + 1
 print                "rownum = %d" % rownum
 return                rownum
 #данная функция печатает всю таблицу  def printall():for                row in sqlselect():
 style='font-size:                9.0pt;'>print row
 return
 # Функция возвращает начальное и конечное время от соответствующего                sql запроса.# Это может быть удобно например для узнавания начального и конечного                времени тестирования
 # определенных тестов.
  def counttime(res):starttime                = res[0][0]
 #print                "starttime = %s" % starttime
 endtime                = res[-1][0]
 return                starttime,endtime
 print                "Start time, End time = %s,%s" % counttime(sqlselect())
 # Эта функция определяет количество пройденых и не пройденных тестов.# Рисует диаграму прохождения тестов в которой каждый пройденый                тест
 # увеличивает вероятость а не пройденый уменьшает. В результате                выполнения
 # будет графический файл в формате png.
  def getstatic():res                = sqlselect('SELECT testnum,status FROM qastat')
 rownum                = 0
 allpassed                = 0
 allfailed                = 0
 for                row in res:
 rownum                = rownum + 1
 
 i =                0
 val                = range(rownum)
 for                row in res:
 val[i]                = 0
 i                = i + 1
 i                = 0
 for                row in res:
 res                = re.search('PASS', row[1])
 if                (res):
 val[int(row[0])]                = val[int(row[0])] + 1
 allpassed                = allpassed + 1
 else:
 val[int(row[0])]                = val[int(row[0])] - 1
 allfailed                = allfailed + 1
 i                = i - 1
 print                "Total test passed = %d" % allpassed
 print                "Total test failed = %d" % allfailed
 return                val
 Вызываем наши функции.  countrow()ret = getstatic()
 drawchart(ret)
 Заключение. В данной статье я попытался создать систему для анализирования                результатов тестирования, используя Python и Mysql. В результате                появилась простая и прозрачная программа, которою можно легко изменить                под свои конкретные нужды. Плюсами использования такого подхода                к тестам является: простота использования, большая скорость работы,                удобный вид полученной статистики, платформо-независимость тестирования,                используется одна база данных. Минусами можно назвать: требование                к наличию сконфигурированной базы Mysql, наличие установленного                языка Python с модулями MySQLdb и matplotlib, применимость только                к консольным тестам, с известным выводом. Необходимые для работы файлы:insert.py show_static.py
 |