среда, 28 ноября 2012 г.

SikuliFirefoxDriver

SikuliFirefoxDriver

SikuliFirefoxDriver расширяет Selenium's FirefoxDriver технологией поиска изображений Sikuli.

Использование:

findImageElement() метод который позволяет находить элемент по его изображению. Например,код ниже откроет страницу Google Code и найдет изображение логотипа Google Code

SikuliFirefoxDriver driver = new SikuliFirefoxDriver();         
driver.get("http://code.google.com");
ImageElement image = driver.findImageElement(new URL("http://code.google.com/images/code_logo.gif"));
Т.к. SikuliFirefoxDriver расширяет Selenium's FirefoxDriver можно использовать все методы доступные  FirefoxDriver.

Установка:

Добавить в Maven зависимости в pom.xml:

        org.sikuli
        sikuli-webdriver
        1.0.1


 Пример:

Google Map example

  1. Selenium: Ввести  "Denver, CO"  поисковым запросом,найти поле поисковика по ID gbqfq
  2. Sikuli:Кликнуть для приближения  Lakewood region.
  3. Sikuli: Кликнуть для приближения Kendrick Lake region.
  4. Sikuli: Кликнуть для переключения вида со спутника.
  5. Sikuli:Кликнуть  для увеличения масштаба.
  6. Selenium: кликнуть по элементу с  ID link
package org.sikuli.webdriver.examples;

import java.io.IOException;
import java.net.URL;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.sikuli.webdriver.ImageElement;
import org.sikuli.webdriver.SikuliFirefoxDriver;

public class GoogleMapExample {
        
        public static void main(String[] args) throws IOException {
                
                SikuliFirefoxDriver driver = new SikuliFirefoxDriver();         
                
          
                driver.get("https://maps.google.com/");
                
             
                WebElement input = driver.findElement(By.id("gbqfq"));
                input.sendKeys("Denver, CO");           
                input.sendKeys(Keys.ENTER);

                ImageElement image;
                
             
                image = driver.findImageElement(new URL("https://dl.dropbox.com/u/5104407/lakewood.png"));
                image.doubleClick()     ;               
                
              
                image = driver.findImageElement(new URL("https://dl.dropbox.com/u/5104407/kendrick_lake.png"));
                image.doubleClick();

                
                image = driver.findImageElement(new URL("https://dl.dropbox.com/u/5104407/satellite.png"));             
                image.click();

               
                image = driver.findImageElement(new URL("https://dl.dropbox.com/u/5104407/plus.png"));
                image.click();
                
               
                WebElement linkButton = driver.findElement(By.id("link"));
                linkButton.click();
                                
        }

}

 

Sikuli+Selenium WebDriver

Sikuli+Selenium WebDriver

Про 2 эти инструмента автоматизатора известно достаточно,расскажу как они могут работать помогая друг другу.
1. Качаем отсюда установщик Sikuli(http://www.sikuli.org/download.html).
2. Создаем новый проект(Пример на Eclipse)
3. Называем его SikuliTest
4. Создаем новый класс

5. Подключаем sikuli-script.jar, selenium-server-standalone-2.25.0.jar, selenium-java-2.25.0.jar  CLASSPATH нашего проекта. 
После этого список подключенных библиотек должен выглядеть как-то так:



7. После подключения создадим и проинициализируем  Screen объект из Sikuli в нашем тесте.

SIKULI + SELENIUM WEBDRIVER

 import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.sikuli.script.App;
import org.sikuli.script.FindFailed;
import org.sikuli.script.Pattern;
import org.sikuli.script.Screen;

public class sikuliFirstTest {

@Test
public void functionName() throws FindFailed {

WebDriver driver = new FirefoxDriver();


driver.get("http://www.google.com");

//Создаем и инициализируем Screen объект  
Screen screen = new Screen();

//Путь к изображению поиска
Pattern image = new Pattern("C:\\searchButton.png");
    
//Ждем 10мс  
screen.wait(image, 10);
    
//кликаем по изображению
screen.click(image);
  }
}


Пример использования без WebDriver:

import org.junit.Test;
import org.sikuli.script.App;
import org.sikuli.script.FindFailed;
import org.sikuli.script.Pattern;
import org.sikuli.script.Screen;

public class sikuliFirstTest {

@Test
public void functionName() throws FindFailed {

//Открываем Firefox через его путь 
App firefox = App.open("c:\\Program Files\\MozillaFirefox\\firefox.exe");

Screen screen = new Screen();
 
Pattern image = new Pattern("C:\\searchButton.png");
    

screen.wait(image, 10);
    

screen.click(image);

   
firefox.close();
  }
}


вторник, 27 ноября 2012 г.

Jmeter SMTP Sampler+Postfix

Jmeter SMTP Sampler+Postfix

Иногда, бывает удобно высылать результаты выполнения тестов Jmeter на  почтовый ящик, как уведомления о корректности их выполнения или для мониторинга правильной работы системы.А когда этот мониторинг нам необходим каждый час,то наша локальная машина нем не подходит,все это же можно развернуть и на виртуалке.

У jmeter есть 2 типа оповещения по email.
Это SMTP Sampler,который выступает в роли обычного сэмплера и его можно использовать в связке с каким-нибудь if controller,или же просто запускать по окончанию теста.Или же Mailer Visualizer, который добавляется как Listener к тесту и по определенным условиям высылает письмо настроенное на успешное или не успешное прохождение теста.

Для того чтобы воспользоваться MailerVisualizer вам необходимо указать в настройках (в поле SMTP host) имя email сервера с открытой (без логина/пароля) ретрансляцией, это может быть или ваш локальный email сервер или email сервер вашей сетки, поддерживающий открытую ретрансляцию только для пользователей внутри сетки.


Если нам понадобился такой локальный smtp,то ничего сложного.
aptitude install postfix
Прежде всего вам надо настроить следующие параметры, отвечающие за домен и имя сервера:
# Имя вашего хоста. По умолчанию берется из системы, но лучше всегда указывать явно
myhostmane = mail.example.com

# Домен вашего сервера. По умолчанию выделяется 
#из имени хоста отбрасыванием первой части, поэтому вручную указывать обычно не нужно
#mydomain = example.com

# Домен, с которого отправляется локальная почта.
 #Автоматически дописывается при необходимости к исходящему адресу
myorigin = $mydomain

# Домены, для которых данный сервер является конечной точкой доставки почты.
# Обычно лучше почтовые домены обслуживать через механизм virtual, поэтому в этом параметре
# чаще всего стоит лишь указать localhost и имя хоста, так, на всякий случай,
# можно вообще оставить значение пустым.
mydestination =
 localhost
 $myhostname

# Мы хотим вообще запретить стандартную локальную доставку,
# поэтому нужно указать пустой список локальных получателей
# Для локальной доставки почты мы будем использовать виртуальные домены
local_recipient_maps =
 
 Теперь все оповещения без проблем достигнут адресата.

пятница, 23 ноября 2012 г.

Распределенная нагрузка Jmeter

Распределенная нагрузка Jmeter.

Бывает,что пользователей которые может предоставить Jmeter нам не хватает.Конечно в таком случае уместнее использовать другой более походящий инструмент вроде Tsung,но лень нам не даст так просто забить на все наши тесты написанные на Jmeter,поэтому попробуем провести большую нагрузку с несколькими машинами.

Ставим на все машины которые хотим для этого использовать Jmeter и запускаем на них JMETER_HOME/bin/jmeter-server

На основной машине мы правим  JMETER_HOME/bin/jmeter.properties
конкретно строчку с “remote_hosts=127.0.0.1”
Например если jmeter-server запущен на 192.168.0.10, 11, 12, 13, и
14, строка будет выглядеть так:
remote_hosts=192.168.0.10,192.168.0.11,192.168.0.12,192.168.0.13,192.168.0.14

Теперь из

Из GUI

Console
jmeter -n -t script.jmx -r  запустит на всех хостах указанных в jmeter.properties
или
jmeter -n -t script.jmx -R server1,server2...  запустит только на указанных хостах

с флагом
-X - Закончит работу с удаленными серверами после теста.

SoapUI+LoadUI

SoapUI+LoadUI

Думаю что такое soapUI для чего и кому рассказывать смысла нет,а вот про достаточно новый инструмент LoadUI с ним в связке я пожалуй расскажу.

На первый взгляд прекрасная штука для тех,кто не очень любит окна вида Grinder,Jmeter.
LoadUI поражает своей красотой интерфейса,все регулируется перетаскиванием элементов на dushboard и подключением их друг к другу.
Dushboard loadUI
Однако написать более-менее сложный тест на loadUI вряд ли удастся: количество окон получится угрожающе большим. Спасает положение возможность разработки тестов на Groovy. Т.е., например, вытащить значение из ответа при помощи regexp вы сможете уже только зная программирование, рычажки тут не помогут.
Стоит отдать должное архитектуре loadUI. После беглого осмотра: динамически меняется heap у агентов, логи ведутся в БД, сам сценарий пишется в xml, плагины написаны на Groovy (не нравится -- поменяй код под себя), в качестве репортера -- JasperReports (сохраняй отчет во что хочешь). Об отчетах стоит сказать отдельно: сравнение разных запусков, совмещение графиков, куча всяких показателей.
В проектах, где тесты -- это воспроизведение бизнес-процесса, думаю, loadUI будет не слишком удобен. Но взглянуть на него обязательно стоит. Как минимум получите эстетическое удовольствие.

Еще одна приятная штука у LoadUI это динамическое изменение нагрузки,прям в процессе тестирования ничего не стоит увеличить нагрузку с 300 до 400 пользователей и отследить как на это отреагирует система.

Есть свои агенты мониторинга за сервером и очень удобное распределение нагрузки между несколькими машинами.



И конечно же полная интеграция с soapUI.Любой тест-кейс из soapUI можно перенестив loadUI для проведения необходимых нагрузок.

А как написать быстрые тесты в soapUI при помощи Recording HTTP думаю все и так знают)

Планирование нагрузки на сервер

Планирование нагрузки на сервер

Решил немного рассказать про планирование нагрузки на сервер,хотя тут будет информация в основном заимствованная с одного из ресурсов(с blogerator.ru)
В общем ситуация такова, что нагрузочное тестирование показало, что сервер может обработать 10 запросов в секунду. Значит ли это, что на практике сервер выдержит такую нагрузку в Интернете?
Вообще говоря ответ скорее будет - нет.
Сейчас разберемся почему.

 

Имеется простая задача.

Дан сервер, синхронно обрабатывающий запросы из Интернет в одном потоке. Т.е. в каждый момент времени сервер может либо обрабатывать один запрос, либо ожидать новые запросы. Запросы становятся в очередь ожидания, если в данный момент сервер занят обработкой другого запроса. Время обработки одного запроса равно 100 мс.
И мы подобрались к основному вопросу: каково будет среднее время ожидания запроса в очереди при средней нагрузке на сервер в 10 запросов в секунду? Правильный ответ — время ожидания будет стремиться к бесконечности.

Как же так? В каком то месте произошло что то внезапное? Дело в том, что средняя и равномерная нагрузка — это «две большие разницы». Средняя нагрузка на сервер может быть представлена в виде процесса Пуассона. Это означает, что в начале первой секунды может сразу прийти 100 запросов, а за последующие 9 секунд — ни одного.
В итоге выходит 10 запросов в секунду за интервал в 10 секунд со средним временем ожидания sum(1..99)/100 * 100 мс = 4.95 секунды.
Рассмотрим другие варианты. Очевидно, что при средней нагрузке, превышающей 10 запросов в секунду, сервер не сможет обрабатывать лишние запросы, что приведет к бесконечному увеличению очереди ожидания запросов.
А что будет, если нагрузка будет ниже максимально допустимой? Например, каково будет среднее время ожидания при 95% нагрузке, т.е. для нашего случая 9.5 запросов в секунду?Если вы думаете,что сейчас самое время расслабиться и пойти погонять чаю, рассчитывая на 0мс,то чай откладывается.
Спешу вас снова огорчить — среднее время ожидания в этом случае будет равно 950 мс , т.е. в 9.5 раз больше времени, необходимого на обработку самого запроса! Идем дальше. Давайте попробуем предположить время ожидания при 90% нагрузке. Нет, вовсе не 900 мс, а 450 мс. ВНЕЗАПНО!
А при какой нагрузке среднее время ожидания будет равно времени, необходимому для обработки запроса? Иными словами, при какой средней нагрузке среднее время ответа от сервера будет равно 200 мс (100 мс ожидание + 100 мс обработка)? Правильный ответ — 66.666...%! Даже при одном запросе в секунду среднее время ожидания будет равно не нулю, а где-то 5.56 мс.

Не очень похоже на адекватные результаты.

Числа получены экспериментальным путем(я верю автору который его проводил,но если нет,то это лучшее розового мира с пони в котором вы находились до этого), после чего была выведена формула.
Вот очень простая функция, написанная на python, которая была использована для моделирования нагрузки на сервер и вычисления среднего времени ожидания.
def NormalizedAvgWaitTime(load_factor, requests_count):
 """
Calculates normalized average wait time for the given 
load factor.
 
Models requests to a synchronous single-threaded server 
using Poisson process and calculates an average wait time 
per request for the given load factor.
 
  Args:
load_factor: a floating point value in the range [0..1).
The value 0 means the server isn't loaded with requests 
at all, the value 1 means the average qps load on the 
server is equivalent to its' maximum capacity.
requests_count: an integer representing the number of 
requests to model. Higher values mean higher precision 
for the returned result.
 
  Returns:
a floating point number representing normalized average 
wait time per request for the given load factor. The 
value 0 means requests are processed immediately, while 
any number W means requests stay in the queue for an 
average W*T seconds, where T is a time required for 
processing a single request on the idle server.
  """
  if not load_factor:
    return 0
  points = sorted(random.random() for i in range(requests_count))
  request_time = load_factor / requests_count
  total_wait_time = 0
  x = points[0]
  for i in range(1, requests_count):
    y = points[i]
    wait_time = request_time - y + x
    if wait_time > 0:
      total_wait_time += wait_time
      y += wait_time
    x = y
  return total_wait_time / load_factor

После того, как были получены экспериментальные данные, осталось подогнать под них формулу.
При load_factor = 1  наша функция стремится к бесконечности. Значит, у нас должна быть дробь, в знаменателе которой присутствует множитель, стремящийся к нулю при load_factor = 1 . На эту роль хорошо подходит (1 — load_factor) . Идем дальше. При load_factor = 0  наша функция равна нулю. Значит, в числителе дроби должен быть множитель, равный нулю при load_factor = 0 . Очевидно, что это и есть load_factor.
Дальше — при load_factor = 0.5 наша функция должна равняться тоже 0.5 . Значит, C*0.5/(1-0.5) = 0.5 .
Откуда C = 0.5 . В итоге формула принимает вид:
NormalizedAvgWaitTime(load_factor) = 0.5*load_factor / (1-load_factor)

Как правильно планировать нагрузку на сервер? 

И вот мы подходим к главному вопросу,то что было сказано выше,должно было натолкнуть на мысль,что результаты наших нагрузочных тестов не совсем объективны.Проблема в том, что поток тестовых запросов не является Пуассоновским процессом, с которым суждено встретиться серверу в production. Если вы сейчас обеспокоились заказчиками или своими проектами,то это всего лишь опасения,хрен с ними,дальше все будет намного лучше.Достаточно найти максимальную нагрузку, выдерживаемую системой по схеме, описанной выше.
После этого по формуле вычисляете допустимую нагрузку в production для заданного среднего времени ожидания запроса. Например, для максимальной нагрузки в 1000 qps и среднего времени ожидания запроса, равного 100% времени обработки запроса:
1 = 0.5*load_factor/(1-load_factor) => load_factor = 1/1.5 = 2/3.
Тогда допустимая нагрузка равна: 1000*2/3 = 666.666... qps .

Выводы

Всегда следите за нагрузкой на системы, обрабатывающие запросы, которые распределены во времени по процессу Пуассона. К таким системам относятся все системы с потенциально большим количеством пользователей. Например, все сервера подключенные к Интернет.

Не допускайте, чтобы средняя нагрузка повышалась более чем на 75% от максимально допустимой, т.к. это ведет к молниеносному увеличению среднего времени ожидания входящих запросов,криков со стороны руководства и заказчиков,месяца без премий,отсутствию серфинга в Калифорнии.

Начало

Начало

В этом блоге я буду писать или репостить вещи,которые мне по каким либо причинам показались интересными или важными.Наверное,большая часть  записей будет сделана именно для себя,то бишь с целю не забыть.
Итак,начну с этого пожалуй.