вторник, 19 января 2021 г.

Python в тестировании. Соединить или склеить пару картинок для ручного сравнения.

    Brief: Понадобилось проверить на сходство два набора картинок путем "склеивания" их в одну и последующее "ручное" сравнение просмотром глазами 👀. В целом такая потребность возникает часто. Применений этому масса. Да и развить это можно до полной автоматизации. Я решил поделиться базовым вариантом, что будет полезно прояснить в начале реализации такого подхода.

    User story: Недавно у меня появилась такая потребность ввиду проверки интересного функционала, который ищет на стоке старые товары аналогичные с уже имеющимся в заказах(но со стоком =0). Разные они лишь в названиях артикулов(поставках). Обнаружив такие позиции код в заказах подтягивает те артикулы, которые есть в наличии. Своеобразная рокировка. Польза огромная, стоки освобождаются, клиенты получают свои покупки не ожидая их от поставщика. Быстро проверить корректность хотелось не только вручную, так как это подразумевает малое количество случаев. Для этого я вытащил из базы данных два списка ссылок на картинки у схожих позиций. Списки были заранее в базе отсортированы по id order item из таблицы заказа. Сомнения оставались в правильности работы алгоритма поиска аналогов. Визуальный контроль результатов был кстати. 

    TO BE: Сразу решил использовать очевидный подход , - склеить, объединить в одно изображение две "соответствующих" фотографии. Потом просмотреть их в вручную.

Алгоритм:

  1. создаём папку для набора будущих объединённых картинок
  2. создаём шаблонную пустую картинку для вставки
  3. забираем из первого списка ссылку на первую картинку
  4. далее запрашиваем по url всё что там есть
  5. переводим этот набор данных в байты и преобразуем в картинку 1
  6. вставляем в начало шаблонной картинки
  7. забираем вторую ссылку из второго списка 
  8. запрашиваем по url все данные
  9. конвертируем полученный набор данных в байты и преобразуем в картинку 2
  10. вставляем, со смещением на примерную длину картинки 1, в шаблонную картинку
  11. сохраняем получившуюся склейку в папку
Relate: Вот список модулей:
import requests
from io import BytesIO
from PIL import Image
import os
Для всех эти задач нам понадобится установить в python библиотеки: 
  • requests  -  для установки нужно использовать следующую команду
    • pip install requests
  • pillow - также "подушка", библиотека для работы с изображениями
    • pip install Pillow
  • библиотека io и os уже предустановлены в Python, в любом случае найти команду на их установку не составит труда.
Code:
import requests
from io import BytesIO
from PIL import Image
import os

#создаем папку для сохранения
path = 'C:\\tmp\\'
try:
os.mkdir(path)
except OSError:
print ("Creation of the directory %s failed" % path)
else:
print ("Successfully created the directory %s " % path)
# объявляем два списка ссылок на картинки
list_im = ['https://bipbap.ru/wp-content/uploads/2018/01/01labgvli1288681954.jpg']
list_im2 = ['https://memax.club/wp-content/uploads/2019/06/1-436.jpg']
# формируем шаблон для склеивания/объединения
new_im = Image.new('RGB', (1240,400))
# разбираем списки ссылок в цикле
for i in range(0, len(list_im)):
# запрашиваем данные по ссылке
response = requests.get(list_im[i])
# преобразуем в байты и формируем картинку
im = Image.open(BytesIO(response.content))
# вставляем в шаблон получившееся
new_im.paste(im, (0, 0))
response2 = requests.get(list_im2[i])
im2 = Image.open(BytesIO(response2.content))
# вставляем вторую картинку со смешением по ширине
new_im.paste(im2, (600, 0))
# сохраняем склейку картинок в папку
new_im.save('C:\\tmp\\test'+str(i)+'.jpg')

Result: Для примера ссылки на картинки взял первые попавшиеся в Google поиске. Результат работы приведён ниже:


Объединяет всё достаточно быстро. У меня было от сотни случаев. Единственный минус придётся вручную проконтролировать соответствие, - просмотрев полученное. 

p.s. В процессе создания много гуглил в поисках схожих вариантов. Только их не так много. В основном примеры с картинками на жестком диске, что в моём случае избыточно.

среда, 21 октября 2015 г.

Планы на тестирование, пустая трата времени? [перевод]

Are Test Plans a Waste of Time? by Andrew Schiano

Должно быть вы, как и многие тестеры, ненавидите тестовые планы. Большинство тестеров попадают в три группы: Группа A – не любит написание тестовых планов, Группа B – думает, что тестовые планы это трата времени, и Группа C – думают, что обе группы A и B правы.
Начнем с группы A. Некоторые тестеры не любят написание тестовых планов, потому что им просто не нравиться писать.  Их неприязнь не столько в том, что они пишут, а с связано тем фактом, что они вообще что-то пишут. Возможно, писанина не подходит их естеству. Один тестер в ответ сказал мне, «Я пишу как третьеклассник».  Это не удивительно, что он не любит их писать – мы хотели бы делать вещи, в которых мы хороши.
Некоторые тестеры не любят написание тестовых планов, потому что они не совсем тестеры – они разработчики, работающие в тестировании.  Они бы предпочли, если бы кто-то другой анализировал функциональную спецификацию, написал тестовый план, и сказал им точно, что им необходимо автоматизировать.
Как у многих тестеров, все мои предыдущие места работы были в программировании. Я думал, написание плана тестирования это просто – пока я не увидел мой первый шаблон тестового плана.  Тестирование производительности? Стрессовое тестирование? Дальне магистральное тестирование? Я быстро понял, что у меня нет идей как писать тестовый план, и я боялся писать один. Но я начал читать планы от тестеров,  которых уважаю, и я начал читать книги по тестированию. Я медленно произвел трансформацию из разработчика к тестеру. Сейчас я люблю написание тестовых планов, потому что я знаю, что это сделает мое тестирование лучше.
Пожалуй, есть много интересных причин, почему тестеры не любят тестовые планы объясняется это тем, что они не думают о полезности планов. Они указывают на тот факт, что большинство планов тестирования, никогда не обновляются. Как только продукт эволюционирует, тестовые планы разсинхронизируются с текущей функциональностью. Я нахожу, что это правда. Из всех тестовых планов написанных мною за мою карьеру, я знаю точно, как много я их обновлял после изменения продукта: НОЛЬ.
Это проблема по двум причинам. Первая, это было бы одно дело, если планы тестирования писались бы быстро и легко; но это не так. В зависимости от функциональности, это может потребовать до недели, чтобы написать солидный подробный тестовый план. Некоторые утверждают, что это время лучше потратить на автоматизацию тестов или выполнять исследовательское тестирование.
Даже хуже, планы тестирования,  которые не синхронизированы с функциональностью продукта, дают не точную информацию читателю. Недавно, я работал над продуктом, который был в состоянии обновления до следующего релиза, меня назначили тестировать функциональность, я был полностью незнаком с ним. Первое что я сделал, был просмотр первоначальных тестовых планов, чтобы узнать, как функции работают, и как это тестировалось впервые. Я предположил, неправильно, что документация была актуальной. В результате, я сообщил о багах  хотя функции работали правильно.
James Whittaker, Директор тестирования в Google, недавно обсуждал значение создания тестовых планах в блоге Google потестированию:
«Что касается того, стоит ли это делать, вообще хорошо, что это другая история. Каждый раз, когда я смотрю на десятки тестовых планов написанных моей командой, я вижу мертвые планы тестирования. Планы написанные, рассмотренные, упомянутые пару раз, а затем заброшенные, так как проект движется в направлении, не задокументированном в плане. Возникает вопрос: если план не нужно беспокоиться обновлять, стоит ли его создавать в первую очередь?
Иногда план отбрасывается потому что он пошел во множество деталей или их слишком мало; третьи, потому что предоставляет значение только для начала тестового усилия, а не в продолжающейся работе. Опять же, если это так, этот план стоит своей стоимости создания, дал ли он ограничение и уменьшение стоимости?
Некоторые тестовые планы содержат простые истины что вероятно в действительности не нужно документировать или предоставляют детализированную информацию,  которая не соответствует ежедневной работе тестера. Во всех этих случаях мы это будет напрасный труд.»
Я согласен, что тут может быть напрасный труд в написании тестового плана. Например, я виновен в том, что трачу очень много времени на корректировку формулировки моих документов. Это тест план, не роман. Маркировка пунктов и приведение в порядок фрагментов предложения – вы не должны тратить время на использование словаря в поиске синонима для слова «характеристика».
Но это не значит что все это напрасный труд. На самом деле, я верю в пользу превышения усилий. Это правильно даже если тестовый план быстро становится устаревшим.
Рассмотрим функциональную документацию: очень похожи на тестовые планы, функциональные спецификации  часто устаревают с развитием продукта. Это не означает, что мы не должны писать функциональные спецификации. Возможно документ «устаревший» и это не обоснованный довод против написания спец документов – или тест планов. Только не делайте ошибку, рассчитывая, что старая спецификация по-прежнему точна.
Одна из наиболее важных причин создания тестового плана это получение ваших мыслей о тестировании функциональности на бумагу из вашей головы. Это разгружает ваш ум и помогает вам думать яснее. А кроме того документируя идею, которую вы получаете во время тестирования особенности, так ни одну не забудете.
Процесс написания часто приводит вас к продумыванию наиболее лучших путей тестирования особенности. Ваш первый проход в письменной форме тестового плана может включить главным образом позитивные функциональные тестовые случаи, а также горстка негативных функциональных тестов. Но в процессе улучшения вашего документа это приведет вас к рассмотрению более негативных случаев, более граничных случаев, больше проблем вокруг масштабируемости и безопасности. Больше времени потратите на планирование вашего тестирования, более полное тестирование будет.
Детализированные тестовые планы могут также помочь вам найти баги в функционале, прежде чем код даже будет реализован, когда они гораздо менее дорогостоящие. Два метода которые прекрасно подходят для поиска дыр проектирования в течении планирования теста это «Таблица решений» и «Диаграммы переходных состояний». Я помню создавая большую Таблицу Решений как часть тестового плана для функций безопасности, которая обнаружила, что почти 10% возможностей включая комбинации, не имеют ожидаемого результата в проектном документе спецификации.
Тестовая документация также полезна для проведения обзора тестового плана.  После создания вашего тестового плана, важно, чтобы его просмотрели другие тестировщики – ни один тестер не сможет продумать все возможные тестовые случаи. Так же полезно, чтобы ваш тестовый план был просмотрен со стороны разработчиков и руководителей проекта. В моем наиболее свежем тестовом плановом обзоре, менеджер программ сказал мне, что одну из особенностей, которую я запланировал проверить, должна быть исключена. В этом же обзоре, разработчик проинформировал меня об существующих проверочных крюках, которые сэкономят мне часы от времени разработки.

Когда тестеры говорят, что не хотят писать тест-планы, я могу посочувствовать. Большинство из нас пришел в этот бизнес, либо потому, что нам нравится программирование или потому что нам нравится ломать вещи, не потому что нам нравится писать документы. Но когда тестеры говорят, что не хотят писать тест-план, потому что это не полезно, я вынужден не согласиться. Хороший тест-план сделает продукт лучше. Что из того что они устаревают? Поскольку Dwight D. Eisenhower и Wile E. Coyote однажды сказал, «планы бесполезны, но планирование просто необходимо.» 

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

Почему 100%-е прохождение тестов - это плохо.[перевод]


Why 100% Test Pass Rates Are Bad by Andrew Schiano

Когда тест показывает оценку 100%, как правило есть причина для ликования. Это означает, что у вашего продукта высокое качество. Тесты, которые так тщательно разработаны, проходят, доказывая, что продукт работает так, как ожидалось. Также показывает, что ваши тестовые случаи высокого качества; результаты воспроизводимы, и они успешно проверяют функциональность продукта. Эта та цель, к которой ты стремился с начала тестирования, правильно? Если это так, то вы выбрали неверную цель.
100%-е прохождение подразумевает, что ваш продукт работает точно, как ожидалось. Задача тестирования, однако, не доказывать, что приложение работает, как ожидалось. В сущности, эта цель может даже не достижима, потому что все сложные приложения имеют дефекты. Какой смысл всё это делать, имея цель, которая не может быть достигнута? Ваша цель должна быть в написании тестов, которые обнажают эти дефекты так, чтобы можно было сделать обоснованное решение об их исправлении.
Другая причина неверной цели 100%-го прохождения в заключается том что, когда все ваши тесты последовательно проходят, они прекращают обеспечивать вас новой информацией. Вы можете наблюдать прекрасный проход тестов каждое утро, и в дальнейшем не обращать внимание на них. Другими словами, как только вы достигнете своей "цели", ваши тесты перестанут помогать вам улучшить ваш продукт.
Чтобы быть справедливым, с точки зрения управления 100%-й проход тестов это верная цель. Так как это убеждает менеджера в качестве продукта. Но если менеджер и тестировщик оба стремятся к совершенному проходу тестов, это не вызывает доверия. В этом случае, никто не ищет баги и 100% проход тестов мало чего значит.
Теперь предположим у вас прекрасный проход тестов, но тестировщики должны стремится доказать, что приложение не работает как ожидалось. Прекрасный проход тестов показывает руководству, что несмотря на факт о том, что вы ищете баги, вы всё ещё не можете найти их. Это дает уверенность руководству в области качества программного обеспечения.
Если у вас 100%-й проход тестов, и есть ещё время до Завершения Всего Тестирования, не думайте что это конец игры. В продукте есть ошибки, и ваши тесты не могут найти их. Измените тесты. Напишите новые. Но продумайте каждый тестовый случай с целью доказать, что программное обеспечение не работает как ожидалось.  Рекомендации могут показаться очевидными, а некоторые тестировщики не подумают в таком плане; они очень сильно заинтересованны иметь гладкий тест и по плану.
Edsger Dijkstra писал, "Тестирование может показать присутствие ошибок, но не их отсутствие." Как только вы измените ваш тип мышления и напишите тесты доказывающие, что продукт не работает, вместо того, чтобы доказывать, что он работает, вы будете удивлены, как насколько больше ошибок вы обнаружите. Это простое изменение сделает из вас лучшего тестировщика, и вашим продуктам будет лучше от этого.

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

Page Object Pattern быстрая визуализация

Сценарий нашего будущего приложения будет вот такой, заметьте я ещё не написал ни строчки кода [Есть такая умная мысль: "A carelessly planned project takes three times longer to complete thanexpecteda carefully planned project takes only twice as long."], Итак приступим:
1. заходим на страницу google.ru;
2. набираем в поиске Selenium;
3. дёргаем список все найденные ответы, возможно бегаем ещё на пять страниц в глубину(организуем постраничный переход), при нахождении Хабрахабра  переходим по его ссылке;
4. проверяем действительно ли мы туда попали, куда хотели, проверяем жёстко с вылетом теста если будет коллизия;
5. на странице habrahabra выбираем статью с названием "Что такое Selenium?";
6. собираем все комментарии к этой статье и сохраняем в файл.

Вот такую схему я быстро накидал в paint, сам я делаю это обычно на бумажке карандашиком, быстренько и без затей. Читается она очень просто, прямоугольники - это страницы сайта, а овалы - это методы которые либо ведут к другой странице[как например:Set Search Request, Gone Link Text], либо остаются на той же странице[как например: Gone On Number Page, Comments Save File]. В схему я намеренно не включаю проверки, они просто захламляют, да и надобавлять их уже после написания "кода" не проблема.




понедельник, 8 октября 2012 г.

Перевёл тесты Selenium WebDriver на браузер Google Chrome

Для работы нам понадобится
1. Java тут всё довольно тривиально, просто всегда делее;
2. Необходимо установить JDK
рис.1
На следующей странице принимаем соглашение и качаем нужный установочный файл(в моём случае это jdk-7u7-windows-x64.exe)
рис.2

3. Eclipse скачиваем в зависимости от нужд могу лишь посоветовать одну из первых трёх(для этого проекта)
рис.3

Сразу к сути дела,  тесты выполняю в Eclipse, распишу всё подетально:
1. Создаём проект, правой кнопкой на молоке New > Java Project,
рис.4
обзываем его exampleProject > Finish 
рис.5

2. Добавляем в проект новый класс

рис.6

 и называем его exampleGoTOGoogle

рис.7

3. Открываем свойства проекта, 
рис.8
далее в Java Build Path > вкладка Libraries > кнопка Add Library > выбираем User Library
рис.9
после нажатия кнопки Next открывается окно User Library > тыкаем на кнопку User Libraries... > кнопку New > даём любое произвольное название, в данном случае sel > кликаем на Ok > Finish.
рис.10

4. Так теперь необходимо добавить в эту пользовательскую библиотеку selenium 
- открываем сайт selenium и скачиваем:
рис.11
после распаковываем, желательно на C:\ диск (в данном примере так "C:\selenium-2.25.0"). Добавляем в пользовательскую библиотеку selenium-java-2.25.0.jar : Выбираем sel > кнопка Edit >  User Libraries > выбираем sel > Add External Jars >  в диалоговом окне отмечаем selenium-java-2.25.0.jar > Открыть
рис.12
ok> Finish >ok. Ещё необходимо добавить всё, что есть в папке lib(находится она в той же папке что и selenium-java-2.25.0.jar), алгоритм действий аналогичен предыдущему добавлению:
рис.13

5. Добавим в наш проект пакет и назовем его start:
рис.14


перетаскиваем наш класс exampleGoTOGoogle в только что созданный пакет start посредством Drag&Drop'а (зажимаем левой кнопкой мыши на классе, тащим его на пакет и отпускаем левую кнопку мыши). В итоге получаем:
рис.15

Приступим к созданию теста, на Selenium WebDriver в браузере Google Chrome.
1.  Вот скрин всего кода
рис.16
как видите "программка" не очень большая. 
Сценарий:
- заходим на страницу www.google.ru;
- набираем в поиске "Selenium";
- дергаем в список(грубо говоря в массив строк) все найденные ссылки;
- из полученного списка выбираем ссылку на Хабрахабр и переходим по ней;
- естественно "жёстко" проверяем(с завалом теста), что страница открылась именно habrahabr;
- чуть чуть ждём. 
1. Сначала цепляем все эти модули 
import static org.junit.Assert.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import static org.junit.Assert.*; - необходим для жёсткой проверки в конце теста;
import java.util.List; - позволит создать список (массив строк) ссылок на странице результата поиска;
import java.util.concurrent.TimeUnit; - тут из названия ясно что работает с time, необходимо для организации задержки;
import org.junit.After; - этот модуль позволяет как бы обозначить метод [в нашем случае это public void tearDown() ] который заработает после окончания теста [After - после];
import org.junit.Before; - этот модуль позволяет как бы обозначить метод [в нашем случае это public void setUp() ] который заработает перед началом теста [Before - перед, до];
import org.junit.Test; - ну этот метод объясняет JUnit что последующий метод и есть тест[у меня это - public void testGoogle()];
import org.openqa.selenium.Keys; - позволяет работать с клавишами;
import org.openqa.selenium.JavascriptExecutor; - открывает возможность вставлять Javascript код в тело WebDriver теста;
import org.openqa.selenium.chrome.ChromeDriver; - это драйвер Google Chrome;
в остальном и так понятно. Вот так это выглядит:

рис.17

Далее создаём переменную[с типом WebDriver] под будущий браузер.
public WebDriver driver;
рис.18

и Метод @Before  который его и инициализирует
рис.19
Тут очень важный момент чтобы тесты запустились в Google Chrome необходимо скачать Драйвер для Google Chrome  у него такая особенность, распакуйте в папку с селениумом, я выбрал вот этот:
рис.20
в коде метода @Before есть строка которая указывает где этот chromedriver лежит
System.setProperty("webdriver.chrome.driver","C:\\selenium-2.25.0\\chromedriver.exe");
только учтите что один символ \ должен экранироваться повторным \, и желательно в пути к файлу не иметь папок с русскими именами, Eclipse не поймёт(у меня не одобряет выдаёт ошибки). Далее мы оговариваем что создаётся новый экземпляр хрома:
driver = new ChromeDriver();
 и задаём ожидание элемента на странице, если его по какой то причине не оказалось(сайт долго грузится, элемент тяжёлый и долго подтягивается и т.п.) задержка в 10 секунд:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Вот код метода, где и происходит самое интересное:
рис.21
 По порядку:
driver.get("http://www.google.ru/");  - открываем браузер и заходим на сайт google.ru
driver.findElement(By.name("q")).sendKeys("selenium"); - на полученной странице находим элемент с параметром name равным "q",  здесь find - поиск Element - элемент, внутри скобок применяется механизм By у которого есть метод name("text") - в свою очередь он ищет все элементы с именем text. sendKeys("selenium"); - тут всё опять просто (send - послать Keys - клавиши) это метод который просто печатает поклавишно принимаемый текст.
driver.findElement(By.name("q")).sendKeys(Keys.ENTER); - после набора текста в этом же поле нажимается клавиша ENTER, она "дёргается" из модуля Keys.
List<WebElement> urls = driver.findElements(By.tagName("h3")); - тут создаётся список веб-элементов(WebElement) с именем urls, в него запихиваются все найденные элементы с тегом h3 (tagName - поиск по тегу). В данном случае все найденные будут содержать ссылки по запросу h3>a.
for (WebElement url : urls) {
if (url.getAttribute("textContent").contains("Хаб")) {
driver.navigate().to(
url.findElement(By.tagName("a")).getAttribute("href"));
break;
}
}
Тут организуется цикл по списку, который посматривает у h3 элемента контекстный текст на присутствие "Хаб"[.contains("Хаб")], в итоге будет переход по отсеянной ссылке[driver.navigate().to()] и дальнейший выход из цикла [break]. Перейдя на искомую страницу нам необходимо дёрнуть JavaScript'ом адрес открывшейся страницы:
String getUrlOpenPage = (String) ((JavascriptExecutor) driver)
.executeScript("return window.document.location.toString();");
 Далее проверяем полученную от JavaScript'а строку на присутствие в ней адреса сайта habrahabr.:
assertTrue(getUrlOpenPage.contains("habrahabr.ru"));
После всех приключений подождём чуть чуть, а именно, 8 секунд:
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
 Заключительная стадия "программы" завершает работу браузера
рис.22
Вот в принципе всё, только ещё один момент, у вас на компьютере должен быть установлен браузер Google Chrome.

Да чуть не забыл, тесты запускаются
рис.23
правой кнопкой на проекте или классе-теста > Run As > # Junit Test.
Но может оказаться так, что JUnit'а нет в Eclipse, его можно установить через Help > Install New Software
рис.24
Хотя скорее всего он уже будет в сборке Eclipse.