2009/07/28

Рассылка результатов тестирования при использовании Selenium+TestNG

Если вы для запуска автоматизированных тестов используете связку Selenium+TestNG, то результаты запуска тестов легко рассылать всем заинтересованным лицам автоматически.

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

Достаточно будет просто просматривать отчеты в вашем почтовом клиенте. Запуск автоматизированных тестов можно настроить с помощью шедулера. Об этом я расскажу позже.

Результаты прогона автоматизированных тестов хранятся в файле /test-output/emailable-report.html. Этот отчет предназначен специально для рассылки по электронной почте всем участникам процесса.

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

Скриншоты в рассматриваемом примере во время прогона автоматизированных тестов помещаются в папку /test-output/screenshots и имеют довольно-таки информативное название.

Например, DailyPack.Administrator_otdelov.Admin_Otdel_5_Clients_
Sorting.testDeleteClients_07_01_2009_17_58.png


DailyPack.Administrator_otdelov – название пакета

Admin_Otdel_5_Clients_Sorting – название класса

testDeleteClients – название метода

07_01_2009_17_58 – время, когда скриншот был получен

Для рассылки результатов я использую JavaMail 1.4.2. Это набор классов для работы с почтовой системой.

Вот так выглядит полученный отчет в The Bat!:



Собственно, код класса для рассылки ниже:


import java.text.SimpleDateFormat;
import java.util.*;
import java.io.*;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Calendar;

public final class DemoMailer {
public static void main( String... aArguments ) throws IOException{
Emailer emailer = new Emailer();

      // Получаем текущую дату

      Calendar c = Calendar.getInstance();

        SimpleDateFormat sdf = new SimpleDateFormat("MM.dd.yyyy kk:mm");

        // от кого будет письмо

        String from = "tester@qa-testlab.com";

        // получатель 1

        String to1 = "tester2@qa-testlab.com";  

        // получатель 2

        String to2 = "developer@qa-testlab.com";

// получатель 3

        String to3 = "pm@qa-testlab.com";

// результаты прогона тестов для какого проекта

        String project = "Book Shop";

        // путь к отчету emailable-report.html

        String path1 = "C:\\B2B_Pack\\test-output\\emailable-report.html";  

// путь к скриншотам

        String path2 = "C:\\B2B_Pack\\test-output\\screenshots";

    emailer.sendEmail(

      from, to1, to2, to3,

       "Test Results for " + project + " " + sdf.format(c.getTime()), path1, path2);

   }

public void sendEmail(

    String aFromEmailAddr, String aToEmailAddr, String aToEmailAddr2, String aToEmailAddr3,

    String aSubject, String attach, String screenpath

  ) throws IOException{

Session session = Session.getDefaultInstance( fMailServerConfig, null );

    MimeMessage message = new MimeMessage( session );

try {

      // добавляем получателя 1

      message.addRecipient(

        Message.RecipientType.TO, new InternetAddress(aToEmailAddr)

      );

     // добавляем получателя 2

      message.addRecipient(

      Message.RecipientType.TO, new InternetAddress(aToEmailAddr2)

      );

// добавляем получателя 3

      message.addRecipient(

      Message.RecipientType.TO, new InternetAddress(aToEmailAddr3)

      );

      // тема письма
message.setSubject( aSubject );

// от кого письмо
message.setFrom(new InternetAddress(aFromEmailAddr));
MimeBodyPart attachFilePart = new MimeBodyPart();
FileDataSource fds = new FileDataSource(attach);
attachFilePart.setDataHandler(new DataHandler(fds));
attachFilePart.setFileName(fds.getName());
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(attachFilePart, "text/html");
Multipart mp = new MimeMultipart();
mp.addBodyPart(attachFilePart);
// аттачим все скриншоты
File dir = new File(screenpath);
String[] children = dir.list();
if (children == null) {
System.out.println("dir does not exist");
} else {
for (int i=0; i                                                                                                                           
String filename = children[i];
System.out.println("Adding: " + filename);
attachFilePart = new MimeBodyPart();
fds = new FileDataSource(screenpath+"\\"+filename);
attachFilePart.setDataHandler(new DataHandler(fds));
attachFilePart.setFileName(fds.getName());
mp.addBodyPart(attachFilePart);
}
}
message.setContent(mp);
Transport.send( message );

      System.out.println("Mail was sent to " + aToEmailAddr + ", " + aToEmailAddr2 + ", " + aToEmailAddr3);
}
catch (MessagingException ex){
System.err.println("Cannot send email. " + ex);
}
}

public static void refreshConfig() {
fMailServerConfig.clear();
fetchConfig();
}

// PRIVATE //
private static Properties fMailServerConfig = new Properties();
static {
fetchConfig();
}

  private static void fetchConfig() {
InputStream input = null;
try {
// конфигурационный файл
input = new FileInputStream("C:\\B2B_Pack\\mail.txt" );
fMailServerConfig.load( input );
}

    catch ( IOException ex ){
System.err.println("Cannot open and load mail server properties file.");
}

    finally {
try {
if ( input != null ) input.close();
}
catch ( IOException ex ){
System.err.println( "Cannot close mail server properties file." );
}
}
}
}                   


Конфигурационный файл для javax.mail (пример)



# Configuration file for javax.mail

# If a value for an item is not provided, then
# system defaults will be used. These items can
# also be set in code.
# Host whose mail services will be used
# (Default value : localhost)
mail.host=zoo. qa-testlab.com
# Return address to appear on emails
# (Default value : username@host)
#mail.from=tester@ qa-testlab.com
# Other possible items include:
#mail.user=irinach@ qa-testlab.com
# mail.store.protocol=
#mail.transport.protocol=POP3
mail.smtp.host=zoo.web100.com.ua
# mail.smtp.user=
# mail.debug=

3 comments:

Anonymous said...

Есть предположения:
1. этот код можно использовать не только для отправки Selenium-отчетов. В нем нет никакой привязки к Selenium, верно?
2. есть ощущение, что это выстрел пушкой по воробьям: для отправки писем с аттачами не обязательно задействовать Java и писать свой код. Вот, к примеру, один из способов: http://www.blat.net/ На Unix - еще легче.

Тем не менее, успехов в ваших начинаниях.

Estrella said...

Это просто один из вариантов реализации.

Если тесты написаны на Java, то почему бы не добавить функционал рассылки отчетов тоже на Java.

Алексей Булат said...

Скажу так - идея не нова (еще в боевом 2005-ом у нас была реализована сия фича), НО, можно отметить, что мало кто ей пользуется сейчас...

Вообще, реализация подобных подходов показывает уровень зрелости системы автоматизации тестирования... Сначала это ежедневный автоматический прогон тестов, потом отправка отчетов на мыло, потом бог его знает что, быть может автоматическое написание тестов :)

PS Как продолжение можно предложить идею выкладывать результатов в виде xml/html на сервер, и отправки ссылки на результат :)

PSS Удачи...