20 февраля 2014 г.

Тестирование аналитики с помощью Webdriver + BrowserMob.



Как мы можем протестировать аналитику на нашем сайте? Ну, например, можно открывать исходный код странички и проверять там наличие java-скрипта, отвечающего за отправку данных аналитики. Сделать это несложно, ведь вебдрайвер содержит метод getPageSource();
Однако это не очень надёжный способ. Скрипт есть, но не обязательно он корректно работает. Вот если бы мы могли удостовериться, что от нашего сайта физически уходят запросы к сайту аналитики. Это можно сделать, если настроить какую-то прослойку между нашим сайтом и сайтом аналитики. Может быть прокси?

BrowserMob Proxy (BMP)

BrowserMob легко интегрируется   вебдрайвером. Запустившись с браузером, BrowserMob собирает все прошедшие через него запросы и складывает в файл HAR(Http-ARchive). Мы можем получить доступ к архиву и найти в нём нужный нам реквест. 
Подробно про этот продукт можно почитать тут: http://bmp.lightbody.net/. Там же найдёте ссылку на скачивание.
Но хватит болтать. Давайте переходить от слов к делу. Попробуем получить google-аналитику непосредственно с  сайта http://www.google.com/analytics/.  Если полезть и проверить эту задачу руками (С помощью HttpFox, например), то мы увидим несколько запросов при открытии домашней страницы сайта.

 

В урле передаются параметры. Их удобнее посмотреть в табе Query String:

 

А теперь займёмся магией…

1. Базовый класс тестов.

Сначала создадим базовый класс для наших тестов. Будем использовать TestNG в качестве фреймворка. Сделаем @BeforeTest и @AfterTest методы. Перед стартом тестов мы будем запускать BrowserMob-сервер, и вебдрайвер. После окончания тестов будем выключать BrowserMob-сервер и закрывать наш браузер. Поехали.
Класс TestBase:

package tests;

import java.util.Properties;
import net.lightbody.bmp.proxy.ProxyServer;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;

public class TestBase {

       Properties propfile;
       ProxyServer server;
       String BaseUrl;
       String RemapHost;
       String PathToFile;
       WebDriver driver;
      
      
       @BeforeTest 
       public void setup() {
             FirefoxProfile profile = new FirefoxProfile();
             server = StartServer();
             Proxy proxy;
                          
             try {
                    proxy = server.seleniumProxy();
                    profile = AddProxysettingsToProfile(profile, proxy);
                    DesiredCapabilities capabilities = createCapabilities(profile, proxy);
                    driver = new FirefoxDriver(capabilities);
             }
            
             catch (Exception e) {
                    e.printStackTrace();
             }
       }
      
       @AfterTest
       public void teardown() throws Exception{
             driver.close();
             driver.quit();
             server.stop();
       }
      
       private DesiredCapabilities createCapabilities(FirefoxProfile profile, Proxy proxy) {
             DesiredCapabilities new_capabilities = new DesiredCapabilities();
             new_capabilities.setCapability(FirefoxDriver.PROFILE, profile);
             new_capabilities.setCapability(CapabilityType.PROXY, proxy);
       return new_capabilities;
       }

       public FirefoxProfile AddProxysettingsToProfile(FirefoxProfile profile, Proxy proxy) {
profile.setAcceptUntrustedCertificates(true);
profile.setAssumeUntrustedCertificateIssuer(true);
profile.setPreference("network.proxy.ssl", "localhost");
profile.setPreference("network.proxy.http", "localhost");
profile.setPreference("network.proxy.ssl_port", 8105);
profile.setPreference("network.proxy.type", 1);
profile.setPreference("network.proxy.no_proxies_on", "");
profile.setProxyPreferences(proxy);
            
return profile;
       }
      
       private ProxyServer StartServer() {
             server = new ProxyServer(8105);
             try {
             server.start();
             server.setCaptureHeaders(true);  
             server.setCaptureContent(true);
             server.newHar("StatisticsHar");
             } catch (Exception e) {
                    e.printStackTrace();
             }
      
       return server;
       }
      
}

            2. Продолжаем. Тест.

Теперь создадим тест, который будет открывать страничку http://www.google.com/analytics/  и проверять, что аналитика отправилась. Незачем писать многословные тесты. Нам будет достаточно 2-х строчек:
1. Открыть страницу
2. Проверить, что реквесты отправились и содержат корректные параметры.

package tests;

import java.util.ArrayList;
import java.util.List;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.core.har.HarEntry;
import net.lightbody.bmp.core.har.HarLog;
import net.lightbody.bmp.core.har.HarNameValuePair;
import net.lightbody.bmp.core.har.HarRequest;

import org.testng.Assert;
import org.testng.annotations.Test;

public class Tests extends TestBase{
      
@Test
public void testcrosswordScore(){
             driver.get("http://www.google.com/analytics/");
              Assert.assertTrue(GA_RequestPresent());
}

// Метод ковыряния в HAR-файле будет многословен,  но разобраться в нём не так сложно:
public ArrayList<String[]> getAnalyticsFromHar() {
       ArrayList<String[]>requests = new ArrayList<String[]>();
       Har har1 = server.getHar();
       HarLog log = har1.getLog();
       List<HarEntry> entries = log.getEntries();
       for (int i =0; i<entries.size(); i++){
              String utmac="", utmp="";
HarEntry entry = entries.get(i);//будем брать каждую из собранных записей по очереди;
             HarRequest request = entry.getRequest(); // берём реквест записи.
             String url = request.getUrl();
             if(url.contains("http://www.google-analytics.com")&&url.contains(".gif")){ // //будем проверять только нужные нам URL    
                    List<HarNameValuePair> queryString = request.getQueryString();
                          for (HarNameValuePair harNameValuePair : queryString) {
                                 String name = harNameValuePair.getName(); //У каждого переданного параметра берём имя
                                 String value = harNameValuePair.getValue(); // и значение
                                 if(name.equals("utmac")) utmac = value; //Ищем параметры с именем utmac и берём их значения
                                 if(name.equals("utmp")) utmp = value; //Ищем параметры с именем utmp и берём их значения
                          }
String[]GAkeys = {utmac,utmp};// складываем найденные значения в массив
                    requests.add(GAkeys); //и добавляем к возвращаемому значению
             }
                    
       }
                
       server.newHar("StatisticsHar");//перетираем har-файл новым
       return requests;
}
      
//Теперь уже проще. Мы получили лист с реквестами. Посмотрим, есть ли там нужные нам параметры:
public boolean GA_RequestPresent(){
ArrayList<String[]> RequestsParameters = getAnalyticsFromHar();
for (String[] requestParameter : RequestsParameters) {
if (requestParameter!=null){
                     if (requestParameter[0].contains("UA-10005-1") && requestParameter[1].contains("/analytics/"))
                    {
                            return true;
                    }
              }     
}
return false;
}
            
}


И вот, таким образом, наш тест будет зелёным, если с нашей страницы реально уходил запрос на http://www.google-analytics.com с параметрами:
utmac = UA-10005-1
utmp = /analytics/
       
Справились :)