Суть идеи такова... гонятся авто-тесты в связке JUnit + Selenium RC, которые в случае нахождения ошибки автоматом создают отчёты об ошибка в багтрекере, как Вам? :)
Для реализации используем связку двух классов в одном из которых уже описанный способ создания скриншотов при прогоне тестов, а во втором тест создающий отчёты о найденных ошибках.
Итак.... гоним первый тест
package seleniumtests;который в случае ошибки на выходе даёт нам скриншот и переменные содержащие суть ошибки.
import com.thoughtworks.selenium.*;
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import javax.imageio.ImageIO;
/**
*
* @author makeenkov
*/
public class googletest extends SeleneseTestCase {
public static String what;
public static String filename;
String time = new SimpleDateFormat("dd.MM.yyyy_HH.mm.SS").format(new java.util.Date());
void recordStep(String name) throws AWTException, IOException {
File screenshot = new File(new File("."), name + ".png");
Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
BufferedImage image = new Robot().createScreenCapture(new Rectangle(0, 0, screenDim.width, screenDim.height));
try {
ImageIO.write(image, "png", screenshot);
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
@Override
public void setUp() {
selenium = new DefaultSelenium("0.0.0.0", 4444, "*firefox", "http://www.google.ru/");
selenium.start();
}
public void test() throws Exception {
System.out.println("Итак начнём: " + time);
selenium.open("http://www.google.ru/");
selenium.waitForPageToLoad("30000");
selenium.selectWindow("Google");
selenium.type("q", "black and white");
selenium.click("btnG");
selenium.waitForPageToLoad("30000");
if (selenium.isTextPresent("Расходные материалы для лазерных принтеров") && selenium.isTextPresent("blacknwhite.ru") && selenium.isTextPresent("Картриджи по оптовым ценам: 589-49-04 Расходные материалы для лазерных принтеров.")) {
System.out.println("Сайт в индексе в топ-5");
} else {
System.out.println("Сайт выпал из индекса или из топ-5");
selenium.windowFocus(); //Gives focus to the currently selected window
selenium.windowMaximize(); //Resize currently selected window to take up the entire screen
recordStep("индекс_топ-5_" + time);
what = "Сайт выпал из индекса или из топ-5" + time;
filename = "индекс_топ-5_" + time + ".png";
}
selenium.close();
selenium.stop();
System.out.println("Конец: " + new SimpleDateFormat("dd.MM.yyyy HH.mm.SS").format(new java.util.Date()));
}
}
Этот класс вызывается из второго класса
package seleniumtests;который в свою очередь вытягивает переменные и скриншот, а дальше создаёт на основе полученных данных отчёт в багтрекинговой системе.
import com.thoughtworks.selenium.*;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
*
* @author makeenkov
*/
public class obts extends SeleneseTestCase {
// googletest gt = new googletest();
@Override
public void setUp() {
selenium = new DefaultSelenium("0.0.0.0", 4444, "*firefox", "http://www.bugtrack-online.com/");
selenium.start();
}
public void test() throws Exception {
System.out.println(googletest.what);
System.out.println(googletest.filename);
if (googletest.what == null) {
System.out.println("Сайт в индексе в топ-5");
} else {
selenium.open("/login_page.php");
selenium.waitForPageToLoad("30000");
selenium.type("username", "йцукен");
selenium.type("password", "123456");
selenium.click("//input[@value='Войти в систему']");
selenium.waitForPageToLoad("30000");
selenium.click("link=Online Bug Tracking System");
selenium.waitForPageToLoad("30000");
if (selenium.isTextPresent("По всем вопросам пишем в этот отчёт...")) {
} else {
selenium.select("project_id", "label=Online Bug Tracking System");
selenium.waitForPageToLoad("30000");
selenium.click("//input[@value='Переключиться']");
selenium.waitForPageToLoad("30000");
}
selenium.click("link=создать отчет");
selenium.waitForPageToLoad("30000");
selenium.select("category", "label=Категории 1");
selenium.select("reproducibility", "label=всегда");
selenium.select("severity", "label=значительная");
selenium.type("summary", "summary="+googletest.what);
selenium.type("description", "description="+googletest.what);
selenium.type("file", "D:\\NetBeansProjects\\seleniumtests\\"+googletest.filename);
selenium.click("//input[@value='Создать отчет']");
selenium.waitForPageToLoad("30000");
}
selenium.close();
selenium.stop();
}
public static Test googletest() {
return (Test) new TestSuite(googletest.class);
}
public static Test obts2() {
return (Test) new TestSuite(obts.class);
}
public static void main(String args[]) {
junit.textui.TestRunner.run(googletest());
junit.textui.TestRunner.run(obts2());
}
}
В итоге получаем вот такого вида отчёт в системе отслеживания ошибок
С точки зрения реализации - интересно, но вот с точки зрения результативности - сомнительно.
ОтветитьУдалитьРешение о баге должен принимать именно человек, на основе логов скрипта.
Если будет ошибка в скрипте, то будет заведена ошибка в BTS на продукт... (можно еще кучу вариаций придумать)
Автоматизация это круто, ей богу, но все автоматизировать зачастую просто не нужно.
Это как раз и есть просто вариант реализации теста...
ОтветитьУдалитьХотя, например, для проверки СЕО меток на странице, самое оно, т.к. по сути не может быть сбоя в тесте ибо он прост до нельзя, а значит ошибки будут только в случае реальных дефектов системы! :)
Похвально.
ОтветитьУдалитьВопросы:
* автотесты всегда бегают четко и ни разу не падают на ровном месте?
* много ли их уже написано?
* они написаны с целью заменить ручное тестирование?
ЗЫ не "Суть идея такова" а "Суть идеи такова".
Спасибо!
ОтветитьУдалитьОтветы:
* я же сказал, это просто размышления, хотя применение несомненно можно найти
* тестов не много, но в некоторых, которые бегают по редко меняющемуся функционалу скриншотилка нашла применение :)
* они идут параллельно ручному тестированию когда функционал новый, а затем остаются только авто-тесты
ЗЫ Алексей, Вы мой верный Ворд :)
Идея реально суперская, что касается применяемости – это зависит от проекта и организации процесса ... но сегодня я услышал очень интересное мнение от одного тестировщика (кстати – работает в Skype) – для него – регистрация бага ручками – это кайф, ради которого он работает и без этого артифакта работа была бы скучнее :-)
ОтветитьУдалитьПроблема очевидна.
ОтветитьУдалитьЕсли приложение простое, как Mantis, то можно надеяться на то, что тестирование через ГУЙ будет более-менее стабильным.
Если же приложение хотя бы где-то будет работать по AJAX - ложные срабатывания, вероятнее всего, станут нормой.
У меня когда-то тестов было мало, и я их полностью контролировал. Ложных срабатываний было много, но они воспринимались как "это мелкое, это временное". Когда тест-сьютов стало больше десяти, начались проблемы с тем, что не они мне помогали, а я их должен был постоянно подфиксивать и контролировать. Они меня начали троллить, и пришлось думать, как их побороть.
Если тест работает криво на моих глазах, я могу понять, произошла ли ошибка, или был найден баг. А если ложное срабатывание будет моментально занесено в трекер, который кто-то еще мониторит - траблы начнутся :)
2 Заметки латвийского айтишника:
ОтветитьУдалитьТут уж кому, что... кто вообще не хочет связываться с автоматизацией и ему доставляет удовольствие тыкаться с системой, а кому то приятней смотреть на результат прохождения написанных им тестов! :)
2 Алексей Лупан:
"пришлось думать, как их побороть." придумали?
Ну, например, такая схема работы... гонятся тесты ночью и заносят баги как при сбоях тестов, так и при сбоях тестируемого объекта, утром приходит тестировщик и проверяет занесённые баги ручками дополняя их необходимой инфой...
С одной стороны это лишняя трата времени, но когда тестов очень много, то иногда проще по занесённому багу ещё раз перепроверить руками, чем искать где что не так....
2 Алексей Лупан:
ОтветитьУдалить"траблы начнутся :)" - ну если захотеть, то думаю можно организовать всё так, чтобы работало с пользой... ИМХО
Ну конечно в случае если такой вариант работы тестов впринципе подходит для тестируемого объекта, а если тесты постоянно ложно срабатывают, то тоже радости мало :)
Раздробили тесты на очень маленькие шаги и начали искать места, на которых происходили непредвиденные сложности.
ОтветитьУдалитьНо места нашли, а как побороть врага, который непонятно когда появляется, еще не знаем :)
Пока что вообще отказались от схемы "запускаем скрипты на ночь", и используем их только как подспорье в ручном тестировании. Появились насильные пит-стопы, которые тормозят исполнение скрипта, дожидаясь от человека определенного решения.
Но это не те автотесты, о которых обычно ведутся разговоры. Те автотесты - юнит-тесты. Мы же не тестируем юниты, мы тестируем бизнес-логику и приложение как продукт, который щупается руками. Мы его и щупаем, просто некоторые моменты делаем с помощью робота (резко сделать статью определенного формата, например, или создать нового юзера с определенным возможностями).
"резко сделать статью определенного формата, например, или создать нового юзера с определенным возможностями" - ну это же можно считать небольшим смоук-тестами,т.е. пробежка по основному функционалу, почему бы в работающие тесты не включить такие фичи...
ОтветитьУдалитьТ.е. у нас, например, авто-тесты ко всему прочему готовят стенды ночью для ручного тестирования, ну собственно как и у Вас, регистрируют клиентов и прочие мелочи. Вот и хотим мы в таких стопроцентно работающих тестах организовать самозанесение :) отчасти для удовольствия собственного ну и для удобства!
Суть идеи интересна - даже спорить не буду :)
ОтветитьУдалитьСказать честно проходили это уже давно :) сделали, запустили, через пару недель нам менеджеры голову чуть не отвернули, когда на выходных что-то с серваком случилось и а базе появилось 300-400 багов - красивых, тепленьких и румяненьких. А все потому что, мы не учли несколько мелких нюансов ,когда стоит открывать багу, а когда нет, :) как проверить её на дубликаты и т.д.
Технический нюанс:
Зачем же багу набивать визуально при помощи селена? Более красиво было бы сделать создание багрепорта напрямую в БД.
Еще, посмотрел. При многопоточном запуске будут грабли, т.к. переменные googletest.what и googletest.filename - статические.
ОтветитьУдалитьА если быть окончательно занудным, то предложу вам ознакомиться с Java Naming Convention, где черным по белому написано, что имена классов начинаются с БОЛЬШОЙ буквы.
К чему я все это? А да, примеры нужно тоже продумывать, т.к. могу использовать 1 к 1 менее опытные товарищи...
"Технический нюанс:"
ОтветитьУдалитьАлексей Б., Вы читаете мои мысли...
Объясню, во-первых, просто через селен веселей в том плане, что показательней :) ну если запустить именно этот кусок, т.е. видим: ага, нашёл тест баг и опа, сам его заносит :) АВТОМАТИЗАЦИЯ!!!
Во-вторых, писать в базу - это лично для меня пройденный этап, это я умею, а с селениумом только начинаю ковыряться.
В-третьих, мне показалось, что SQL-запросы никому не интересны и для блога немного громоздки...
А в остальном разницы нет, кому как хочется!
Алексей Б., касательно моих косяков по коду, тут да... я совсем так сказать "лошара"...
ОтветитьУдалить