Как локализовать ошибку

В этой статье мы расскажем о том, что делает QA-специалист, когда он находит тот или иной баг. Также рассмотрим, какие бывают дефекты и с чем их «едят».

Основные термины:

Дефект (или баг)  — изъян в компоненте или системе, который может привести компонент или систему к невозможности выполнить требуемую функцию. Дефект, обнаруженный во время выполнения, может привести к отказам компонента или системы. Например: невозможно сохранить данные после заполнения анкеты.

Ошибка — действие человека, которое может привести к неправильному результату. Например: ввод букв в поле для ввода даты (должны приниматься только цифры) с последующим сохранением данных.

Отказ (failure)  — отклонение компонента или системы от ожидаемого результата, выполнения, эксплуатации. Например: при переходе на следующую страницу анкеты данные предыдущей страницы затираются.

Классификация багов

  • Функциональные дефекты  — в этом случае приложение функционально работает не так, как задумано. Например:

— не сохраняются изменения данных в профиле; 
— не работает добавление комментария; 
— не работает удаление товара из корзины; 
— не работает поиск. 

  • Визуальные дефекты  — в этом случае  приложение выглядит не так, как задумано.

— текст вылезает за границы поля; 
— элемент управления сайтом наслаивается на нижестоящий элемент; 
— не отображается картинка. 

  • Логические дефекты  — в этом случае приложение работает неправильно с точки зрения логики. 

— можно поставить дату рождения «из будущего», а также несуществующие даты — 31 февраля, 32 декабря и т.п.; 
— можно сделать заказ, не указав адрес доставки; 
— логика поиска работает неправильно. 

  • Дефекты контента

— орфографические и пунктуационные ошибки; 
— картинка товара не соответствует карточке товара; 
— конвертация валют идет по неправильному курсу (калькулятор считает правильно, но при программировании указан неверный курс). 

  • Дефекты удобства использования — в этом случае приложение неудобно в использовании. 

— отсутствие подсветки или уведомления об ошибке при некорректно заполненных полях формы;
— сброс всех данных при ошибке заполнения регистрационной формы; 
— перегруженный интерфейс. 

  • Дефекты безопасности  — в этом случае могут быть затронуты пользовательские данные, есть риск падения системы и т.п. 

— можно получить логин, пароль в результате использования SQL-инъекций; 
— неограниченное время жизни сессии после авторизации.

Итак, мы рассмотрели типы и виды дефектов. Теперь расскажем о том, как их документировать.  

QA баги.png

Документирование ошибок

Отчет об ошибке (Bug Report)  — это документ, описывающий ситуацию или последовательность действий, приведшую к некорректной работе объекта тестирования, с указанием причин и ожидаемого результата.

«Следующий этап заключается в документировании ошибок»,  — могли бы подумать вы, но оказались бы неправы. 

Нельзя просто взять и задокументировать найденный дефект. Прежде всего, важно выполнить локализацию. 

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

Перепроверка дефекта

Нужно проверить себя еще раз: воспроизвести баг снова при тех же условиях. Если ошибка не повторилась при очередном тестировании, то нужно разобраться, точно ли были соблюдены все действия и шаги воспроизведения, приведшие к этому результату. Возможно, дефект появляется только при первоначальной загрузке системы (при первом использовании). Для того, чтобы более точно определить условия воспроизведения ошибки, необходимо эту ошибку локализовать. 

Локализация дефекта

Чтобы локализовать баг, необходимо собрать максимальное количество информации о его воспроизведении:

  • Выявить причины возникновения дефекта

Например, не проходит восстановление пароля. Необходимо выявить, откуда приходит запрос на сервер в неверном формате  — от backend либо frontend. 

  • Проанализировать возможность влияния найденного дефекта на другие области

Например, в одной из форм, которую редко используют, возникает ошибка при нажатии на кнопку «Редактировать». Если в качестве временного варианта решения проблемы скрыть кнопку, это может повлиять на аналогичную форму в другом окне/вкладке, к которой пользователи обращаются чаще. Для качественного анализа необходимо знать, как работает приложение и какие зависимости могут быть между его частями. 

  • Отклонение от ожидаемого результата

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

  • Исследовать окружение

Необходимо воспроизвести баг в разных операционных системах (iOS, Android, Windows и т.д.) и браузерах (Google Chrome, Mozilla, Internet Explorer и др.). При этом нужно проверить требования к продукту, чтобы выяснить, какие системы должны поддерживаться. Некоторые приложения работают только в определенных ОС или браузерах, поэтому проверять другие варианты не нужно. 

  • Проверить на разных устройствах

Например, desktop-приложение предназначено для использования на компьютерах, поэтому зачастую нет необходимости тестировать его на мобильных устройствах. Для смартфонов в идеале должна быть разработана отдельная мобильная версия, которую, в свою очередь, нет смысла тестировать на компьютерах. Кроме того, есть web-приложения, которые могут работать и на компьютерах, и на мобильных устройствах, а тестировать их нужно на всех типах устройств. Для тестирования можно использовать эмулятор той или иной среды, но в рамках статьи мы не будем затрагивать этот вопрос.

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

  • Проверить в разных версиях ПО

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

  • Проанализировать ресурсы системы

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

Для того, чтобы оптимизировать сроки тестирования, мы рекомендуем использовать техники тест-дизайна

Фиксирование доказательств

Доказательства воспроизведения бага нужно фиксировать при помощи логов, скринов или записи экрана. 

  • Логи (лог-файлы или журнал) — это файлы, содержащие системную информацию работы сервера или компьютера, в них хранят информацию об определенных действиях пользователя или программы. Опытному разработчику бывает достаточно посмотреть в логи, чтобы понять, в чем заключается ошибка. Обычно логи прикрепляют к баг-репорту в виде .txt-файла.

Live-логирование – это снятие системных логов в режиме реального времени. Для этого можно использовать следующие программы: Fiddler, Visual Studio для Windows, iTools, Xcode для iOS, Android Debug Monitor, Android Studio для Android и др. 

  • Скрин (снимок) экрана. При ошибках  в интерфейсе снимок помогает быстрее разобраться в проблеме. Программ для снятия скриншотов очень много, каждый QA-специалист может использовать те, которые ему наиболее удобны: Jing, ShareX, Lightshot и др. 
  • Скринкаст (англ. screen – экран, broadcasting – трансляция) – это запись видеоизображения с экрана компьютера или другого цифрового устройства. Это один из самых эффективных способов поделиться тем, что происходит на экране монитора. Таким способом QA-специалисту легко наглядно показать ошибки в работе любого программного продукта. Сделать запись с экрана помогут незаменимые инструменты любого QA-специалиста: Snagit, Monosnap, Movavi Screen Capture, Jing, Reflector, ADB Shell Screenrecord, AZ Screen Recorder и др. 
  • Рекордер действий. Программные средства дают возможность  воспроизвести все записанные движения мышки и действия, производимые на клавиатуре компьютера. Примеры программ – Advanced Key and Mouse Recorder для desktop-платформ.

QA.png

Оформление баг-репорта

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

Дефект, который не задокументирован – не найден! 

Когда вся необходимая информация собрана, а баг локализован, можно приступать к оформлению баг-репорта в таск-трекере. Чем точнее описание бага, тем меньше времени нужно для его исправления. Список атрибутов для каждого проекта индивидуален, но некоторые из них – например, шаги воспроизведения, ожидаемый результат, фактический результат – присутствуют практически всегда. 

Атрибуты баг-репорта:

1. Название

Баг должен быть описан кратко и ёмко, иметь понятное название. Это поможет разработчику разобраться в сути ошибки и в том, может ли он взять этот случай в работу, если занимается соответствующим разделом системы. Также это позволяет упростить подключение новых специалистов на проект, особенно если разработка ведется много лет подряд, а запоминать баги и отслеживать их в таск-трекере становится все сложнее. Название проекта можно составлять по принципу «Где? Что? Когда?» или «Что? Где? Когда?», в зависимости от внутренних правил команды. 

Например:

Где происходит?  — В карточке клиента (в каком разделе системы).

Что именно происходит?  — Не сохраняются данные.

Когда происходит?  — При сохранении изменений.

2. Проект (название проекта)

3. Компонент приложения

В какой части функциональности тестируемого продукта найден баг.

4. Номер версии

Версия продукта, ветка разработки, в которой воспроизводится ошибка.

5. Критичность

Этот атрибут показывает влияние дефекта на функциональность системы, например:

· Blocker  — дефект, блокирующий использование системы.

· Critical  — ошибка, которая нарушает основную бизнес-логику работы системы.

· Major  — ошибка, которая нарушает работу определенной функции, но не всей системы.

· Minor  —  незначительная ошибка, не нарушающая бизнес-логику приложения, например, ошибка пользовательского интерфейса.

· Trivial  — малозаметная, неочевидная ошибка. Это может быть опечатка, неправильная иконка и т.п.

6. Приоритет

Приоритет определяет, насколько срочно нужно исправить ошибку. Обычно выделяют следующие виды приоритетов:

High  — ошибка должна быть исправлена как можно скорее, является критичной для проекта.
Medium  — ошибка должна быть исправлена, но её наличие не является критичным для проекта.
Low  — ошибка должна быть исправлена, но не требует срочного решения.

7. Статус

Статус указывает стадию жизненного цикла бага, взят он в работу или уже решен. Примеры: to do, in progress, in testing (on QA), done. В зависимости от особенностей проекта возможны дополнительные статусы (например, аналитика).

8. Автор баг-репорта

9. На кого назначен

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

10. Окружение

Где найден баг: операционная система, наименование и версия браузера. 

11. Предусловие (если необходимо)

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

12. Шаги воспроизведения

Один из самых важных атрибутов  — описание шагов, которые привели к нахождению бага. Оптимально использовать 5-7 понятных и кратких шагов для описания бага, например:
1. Открыть (…)
2. Кликнуть (…)
3. Ввести в поле А значение N1
4. Ввести в поле B значение N2
5. Кликнуть кнопку «Calculate»

13. Фактический результат

Что произошло после воспроизведения указанных выше шагов.

14. Ожидаемый результат

Что должно произойти после воспроизведения шагов тестирования, согласно требованиям.

15. Прикрепленный файл

Логи, скриншоты, видеозапись экрана  — всё, что поможет разработчику понять суть ошибки и исправить ее.

После составления баг-репорта обязательно нужно проверить его, чтобы избежать ошибок или опечаток.

Локализация и оформление багов  — необходимые составляющие работы QA-специалиста с программным продуктом. Приглашаем подробнее ознакомиться с услугами тестирования и обеспечения качества в SimbirSoft.

В комментариях к одной из моих статей про базовые команды Linux shell для тестировщиков справедливо заметили, что в ней не было указано применение команд в процессе тестирования. Я подумал, что лучше поздно, чем никогда, поэтому решил рассказать историю Backend QA-инженера Вани, который столкнулся с неожиданным поведением сервиса и попытался разобраться, где именно случилась ошибка.

Что тестировал Ваня

Ваня знал, что ему предстоит тестировать связку «nginx + сервис».

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

В качестве сервиса выступает дефолтный HTTP сервер Python SimpleHTTPServer, который в ответ на запрос без параметров выводит содержимое текущей директории:

[root@ivan test_dir_srv]# ls -l
total 0
-rw-r--r-- 1 root root 0 Aug 25 11:23 test_file
[root@ivan test_dir_srv]# python3 -m http.server --bind 127.0.0.1 8000
Serving HTTP on 127.0.0.1 port 8000 (http://127.0.0.1:8000/) ...

Nginx же сконфигурирован следующим образом:

upstream test {
    server 127.0.0.1:8000;
}

server {
    listen       80;

    location / {
        proxy_pass http://test;
    }
}

Ване нужно было протестировать один-единственный тест-кейс: проверить, что запрос на / работает. Он проверил, и всё работало:

MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href="test_file">test_file</a></li>
</ul>
<hr>
</body>
</html>

Но затем в один момент на тестовом стенде разработчики что-то обновили, и Ваня получил ошибку:

MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>

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

Первая мысль Вани: логи

Действительно, если случилась ошибка, то нужно просто найти её в лог-файле. Но сначала нужно найти сам лог-файл. Ваня полез в Google и узнал, что часто логи лежат в директории /var/log. Действительно, там нашлась директория nginx:

[root@ivan ~]# ls /var/log/nginx/
access.log  access.log-20200831  error.log  error.log-20200831

Иван посмотрел последние строчки error лога и понял, в чём дело: разработчики ошиблись в конфигурации nginx, в порт upstream закралась опечатка.

[root@ivan ~]# tail /var/log/nginx/error.log
2020/08/31 04:36:21 [error] 15050#15050: *90452 connect() failed (111: Connection refused) while connecting to upstream, client: 31.170.95.221, server: , request: "GET / HTTP/1.0", upstream: "http://127.0.0.1:8009/", host: "12.34.56.78"

Какой можно сделать из этого вывод? Логи — лучший друг тестировщиков и разработчиков при локализации ошибок. Если есть какое-то неожиданное поведение сервиса, а в логах при этом ничего нет, то это повод вернуть задачу в разработку с просьбой добавить логов. Ведь если б nginx не писал в лог о неудачной попытке достучаться до апстрима, то, согласитесь, искать проблему было бы сложнее?

В тот момент Ваня задумался: «А что, если бы в nginx логи лежали в другой директории? Как бы я их нашёл?» Через пару лет у Вани будет больше опыта работы с сервисами в Linux, и он будет знать, что путь к лог-файлу часто передают сервису аргументом командной строки, либо он содержится в файле конфигурации, путь к которому также часто передают сервису аргументом командной строки. Ну и в идеале путь к лог-файлу должен быть прописан в документации сервиса.

Кстати, через файл конфигурации можно найти путь к лог-файлу и в nginx:

[root@ivan ~]# ps ax | grep nginx | grep master
root     19899  0.0  0.0  57392  2872 ?        Ss    2019   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
[root@ivan ~]# grep "log" /etc/nginx/nginx.conf
error_log  /var/log/nginx/error.log warn;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    access_log  /var/log/nginx/access.log  main;

А что если в логах ничего нет?

В свободное время Ваня решил подумать, а как бы он справился с задачей, если бы nginx не писал ничего в лог. Ваня знал, что сервис слушает порт 8000, поэтому решил посмотреть трафик на этом порту на сервере. С этим ему помогла утилита tcpdump. При правильной конфигурации он видел запрос и ответ:

Дамп трафика на порту 8000

[root@ivan ~]# tcpdump -nn -i lo -A port 8000
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
09:10:42.114284 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [S], seq 3390176024, win 43690, options [mss 65495,sackOK,TS val 830366494 ecr 0,nop,wscale 8], length 0
E..<..@.@..............@.............0.........
1~c.........
09:10:42.114293 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [S.], seq 4147196208, ack 3390176025, win 43690, options [mss 65495,sackOK,TS val 830366494 ecr 830366494,nop,wscale 8], length 0
E..<..@.@.<..........@...110.........0.........
1~c.1~c.....
09:10:42.114302 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 1, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4..@.@..............@.....111.....(.....
1~c.1~c.
09:10:42.114329 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [P.], seq 1:88, ack 1, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 87
E.....@.@..b...........@.....111...........
1~c.1~c.GET / HTTP/1.0
Host: test
Connection: close
User-Agent: curl/7.64.1
Accept: */*

09:10:42.114333 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [.], ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4R/@.@............@...111...p.....(.....
1~c.1~c.
09:10:42.115062 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [P.], seq 1:155, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 154
E...R0@.@............@...111...p...........
1~c.1~c.HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.7.2
Date: Mon, 07 Sep 2020 13:10:42 GMT
Content-type: text/html; charset=utf-8
Content-Length: 340

09:10:42.115072 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 155, win 175, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4.@.@..............@...p.11......(.....
1~c.1~c.
09:10:42.115094 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [P.], seq 155:495, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 340
E...R1@.@..<.........@...11....p.....|.....
1~c.1~c.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href="test_file">test_file</a></li>
</ul>
<hr>
</body>
</html>

09:10:42.115098 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 495, win 180, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4.
@.@..............@...p.13......(.....
1~c.1~c.
09:10:42.115128 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [F.], seq 495, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4R2@.@............@...13....p.....(.....
1~c.1~c.
09:10:42.115264 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [F.], seq 88, ack 496, win 180, options [nop,nop,TS val 830366495 ecr 830366494], length 0
E..4..@.@..............@...p.13 .....(.....
1~c.1~c.
09:10:42.115271 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [.], ack 89, win 171, options [nop,nop,TS val 830366495 ecr 830366495], length 0
E..4R3@.@............@...13 ...q.....(.....
1~c.1~c.
^C
12 packets captured
24 packets received by filter
0 packets dropped by kernel

При неправильной конфигурации (с портом 8009 в апстриме nginx) на порту 8000 никакого трафика не было. Ваня обрадовался: теперь даже если разработчики забыли реализовать запись в лог при сетевых ошибках, всё равно можно хотя бы узнать, идёт ли трафик на нужный хост или порт.

Какой вывод можно сделать из этой истории? Даже если логов нет, в Linux есть утилиты, которые могут помочь с локализацией проблем.

А если не сеть?

Всё хорошо работало, но однажды Ваня снова получил ошибку, на этот раз другую:

MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: 404</p>
        <p>Message: File not found.</p>
        <p>Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.</p>
    </body>
</html>

Ваня снова зашёл на сервер, но в этот раз проблема не была связана с сетью. В логе сервиса тоже было написано File not found, и Ваня решил разобраться, почему внезапно появилась такая ошибка. Он знает, что есть процесс python3 -m http.server, но не знает, содержимое какой директории выводит этот сервис (или, другими словами, какая у этого процесса current working directory). Он узнаёт это с помощью команды lsof:

[root@ivan ~]# ps aux | grep python | grep "http.server"
root     20638  0.0  0.3 270144 13552 pts/2    S+   08:29   0:00 python3 -m http.server
[root@ivan ~]# lsof -p 20638 | grep cwd
python3 20638 root  cwd    DIR     253,1      4096 1843551 /root/test_dir_srv2

Также это можно сделать с помощью команды pwdx или с помощью директории proc:

[root@ivan ~]# pwdx 20638
20638: /root/test_dir_srv2
[root@ivan ~]# ls -l /proc/20638/cwd
lrwxrwxrwx 1 root root 0 Aug 31 08:37 /proc/20638/cwd -> /root/test_dir_srv2

Такая директория действительно есть на сервере, и в ней лежит файл с именем test_file. В чём же дело? Иван погуглил и нашёл утилиту strace, с помощью которой можно смотреть, какие системные вызовы выполняет процесс (про strace, кстати, есть хорошая статья на Хабре, и даже не одна). Можно либо запускать новый процесс через strace, либо подключаться этой утилитой к уже запущенному процессу. Ване подходил второй вариант:

Вывод утилиты strace

[root@ivan ~]# strace -ff -p 20638
strace: Process 20638 attached
restart_syscall(<... resuming interrupted poll ...>) = 0
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 1 ([{fd=4, revents=POLLIN}])
accept4(4, {sa_family=AF_INET, sin_port=htons(57530), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC) = 5
clone(child_stack=0x7f2beeb28fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f2beeb299d0, tls=0x7f2beeb29700, child_tidptr=0x7f2beeb299d0) = 21062
futex(0x11204d0, FUTEX_WAIT_PRIVATE, 0, NULLstrace: Process 21062 attached
 <unfinished ...>
[pid 21062] set_robust_list(0x7f2beeb299e0, 24) = 0
[pid 21062] futex(0x11204d0, FUTEX_WAKE_PRIVATE, 1) = 1
[pid 20638] <... futex resumed> )       = 0
[pid 20638] futex(0x921c9c, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 27, {1598879772, 978949000}, ffffffff <unfinished ...>
[pid 21062] futex(0x921c9c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x921c98, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
[pid 20638] <... futex resumed> )       = 0
[pid 20638] futex(0x921cc8, FUTEX_WAIT_PRIVATE, 2, NULL <unfinished ...>
[pid 21062] futex(0x921cc8, FUTEX_WAKE_PRIVATE, 1) = 1
[pid 20638] <... futex resumed> )       = 0
[pid 20638] futex(0x921cc8, FUTEX_WAKE_PRIVATE, 1) = 0
[pid 20638] poll([{fd=4, events=POLLIN}], 1, 500 <unfinished ...>
[pid 21062] recvfrom(5, "GET / HTTP/1.1\r\nConnection: upgr"..., 8192, 0, NULL, NULL) = 153
[pid 21062] stat("/root/test_dir_srv/", 0x7f2beeb27350) = -1 ENOENT (No such file or directory)
[pid 21062] open("/root/test_dir_srv/", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 21062] write(2, "127.0.0.1 - - [31/Aug/2020 09:16"..., 70) = 70
[pid 21062] write(2, "127.0.0.1 - - [31/Aug/2020 09:16"..., 60) = 60
[pid 21062] sendto(5, "HTTP/1.0 404 File not found\r\nSer"..., 184, 0, NULL, 0) = 184
[pid 21062] sendto(5, "<!DOCTYPE HTML PUBLIC \"-//W3C//D"..., 469, 0, NULL, 0) = 469
[pid 21062] shutdown(5, SHUT_WR)        = 0
[pid 21062] close(5)                    = 0
[pid 21062] madvise(0x7f2bee329000, 8368128, MADV_DONTNEED) = 0
[pid 21062] exit(0)                     = ?
[pid 21062] +++ exited with 0 +++
<... poll resumed> )                    = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500^Cstrace: Process 20638 detached
 <detached ...>

Обычно вывод strace довольно объёмный (а может быть и очень большим), поэтому удобнее сразу перенаправлять его в файл и потом уже искать в нём нужные системные вызовы. В данном же случае можно сразу обнаружить, что сервис пытается открыть директорию /root/test_dir_srv/ — кто-то переименовал её и не перезапустил после этого сервис, поэтому он возвращает 404.

Если сразу понятно, какие именно системные вызовы нужно посмотреть, можно использовать опцию -e:

[root@ivan ~]# strace -ff -e trace=open,stat -p 20638
strace: Process 20638 attached
strace: Process 21396 attached
[pid 21396] stat("/root/test_dir_srv/", 0x7f2beeb27350) = -1 ENOENT (No such file or directory)
[pid 21396] open("/root/test_dir_srv/", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 21396] +++ exited with 0 +++
^Cstrace: Process 20638 detached

Вывод: иногда можно немножко «залезть под капот» процессу, а помогает с этим strace. Так как эта утилита выводит все системные вызовы, которые использует процесс, то с её помощью также можно находить и сетевые проблемы (например, к какому хосту/порту пытается подключиться процесс), что делает её довольно универсальным инструментом дебага. Также существует похожая утилита ltrace.

Есть ли что-то ещё?

Ваня на этом не остановился и узнал, что есть GNU Project Debugger — GDB. С его помощью можно «залезть» в процесс и даже немного модифицировать его. И Ваня решил попробовать обнаружить последнюю ошибку с помощью GDB. Он предположил, что раз сервис выводит содержимое директории, то можно попробовать поставить breakpoint на функции open() и посмотреть, что будет:

Вывод утилиты gdb

[root@ivan ~]# gdb -p 23998
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-119.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Attaching to process 23998
…
… <здесь много сообщений о загрузке символов и отсутствии debugging symbols...>
...
0x00007f2284c0b20d in poll () at ../sysdeps/unix/syscall-template.S:81
81	T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
Missing separate debuginfos, use: debuginfo-install keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-34.el7.x86_64 libcom_err-1.42.9-13.el7.x86_64 libgcc-4.8.5-36.el7.x86_64 libselinux-2.5-14.1.el7.x86_64 openssl-libs-1.0.2k-16.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-18.el7.x86_64
(gdb) set follow-fork-mode child
(gdb) b open
Breakpoint 1 at 0x7f2284c06d20: open. (2 locations)
(gdb) c
Continuing.
[New Thread 0x7f227a165700 (LWP 24030)]
[Switching to Thread 0x7f227a165700 (LWP 24030)]

Breakpoint 1, open64 () at ../sysdeps/unix/syscall-template.S:81
81	T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) n
83	T_PSEUDO_END (SYSCALL_SYMBOL)
(gdb) n
_io_FileIO___init___impl (opener=<optimized out>, closefd=<optimized out>, mode=<optimized out>, nameobj=0x7f227a68f6f0, self=0x7f227a68f6c0) at ./Modules/_io/fileio.c:381
381	                Py_END_ALLOW_THREADS
(gdb) n
379	                self->fd = open(name, flags, 0666);
(gdb) n
381	                Py_END_ALLOW_THREADS
(gdb) print name
$1 = 0x7f227a687c90 "/root/test_dir_srv/"
(gdb) q
A debugging session is active.

	Inferior 1 [process 23998] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/local/bin/python3.7, process 23998
[Inferior 1 (process 23998) detached]

После команды c (continue) Ваня в другой консоли запустил curl, попал в дебаггере в точку останова и стал выполнять эту программу (то есть сервис) по шагам. Как только он нашёл в коде open по какому-то пути name, он вывел значение этой переменной и увидел «/root/test_dir_srv/».

GDB — это мощный инструмент, и здесь описан простейший вариант его использования. Иногда он может помочь в воспроизведении каких-либо сложных кейсов (например, можно приостановить процесс в нужный момент и воспроизвести состояние гонки), также он помогает с чтением core dump файлов.

А что если Docker?

В один момент DevOps решили, что сервис теперь будет деплоиться Docker-контейнером, и нужно было провести ретест всех кейсов, которые нашёл Ваня. Ваня без проблем нагуглил следующее:

  1. Использовать tcpdump, strace и gdb можно и внутри контейнера, но нужно иметь ввиду Linux capabilities (есть статья, которая объясняет, почему strace не работал в контейнере без —cap-add=SYS_PTRACE).
  2. Можно использовать опцию —pid.

Но ему стало интересно, можно ли посмотреть весь трафик, идущий в контейнер (или из контейнера), прям с хоста. У tcpdump есть возможность выводить трафик какого-либо интерфейса (опция -i), каждому контейнеру соответствует один виртуальный интерфейс veth (это можно увидеть, например, через ifconfig или ip a), но как понять, какому контейнеру какой интерфейс соответствует? Если контейнер не использует host networking, то внутри него будет сетевой интерфейс eth0, через который он может общаться по сети с другими контейнерами и хостом. Остаётся лишь найти, ifindex какого интерфейса на хосте совпадает с iflink интерфейса eth0 контейнера (что это означает можно почитать здесь).

[root@ivan ~]# for f in `ls /sys/class/net/veth*/ifindex`; do echo $f; cat $f; done | grep -B 1 `docker exec test_service_container cat /sys/class/net/eth0/iflink` | head -1
/sys/class/net/veth6c18dba/ifindex

Теперь можно запускать tcpdump для интерфейса veth6c18dba:

tcpdump -i veth6c18dba

Но есть способ проще: можно найти IP-адрес контейнера в его сети и слушать трафик на нём:

[root@ivan ~]# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test_service_container
172.17.0.10
[root@ivan ~]# tcpdump -i any host 172.17.0.10

Вывод: дебаг в Docker-контейнере — это не страшно. Утилиты в нём работают, а для чтения логов можно использовать docker logs.

Выводы

Как ответственный инженер, Ваня решил кратко законспектировать новую для себя информацию во внутренней базе знаний. Вот что он написал:

  • Логи — лучший друг человека. Если встречается неожиданное поведение сервиса и при этом он не пишет ничего в лог — это повод попросить разработчиков добавить логов.
  • Иногда бывает, что локализовать ошибку надо, даже если в логах ничего нет. К счастью, в Linux есть много утилит, которые помогают с этим.
  • С дебагом любых сетевых коммуникаций помогает tcpdump. Он помогает видеть, какой трафик откуда и куда идёт на сервере.
  • Заглянуть «внутрь» процесса помогают утилиты strace, ltrace и gdb.
  • Всё это можно использовать, если сервис работает в Docker-контейнере.
  • Много информации о процессе есть в директориях /proc/PID. Например, в /proc/PID/fd находятся симлинки на все открытые процессом файлы.
  • Также помочь получить различную информацию о системе, файлах или процессах могут утилиты ps, ls, stat, lsof, ss, du, top, free, ip, ldconfig, ldd и прочие.

Надеюсь, вам была полезна эта история, и хотя бы однажды она поможет вам понять, в чём дело, когда вы будете что-то дебажить в Linux. Если Ваня что-то упустил, делитесь этим в комментариях!

#1

single player

    Новый участник

  • Members
  • Pip

  • 11 сообщений

Отправлено 21 сентября 2006 — 17:34

найти ошибку недостаточно. нужно ее качественно локализовать. делимся опытом:)

я себе представляю процесс поиска возможных причин примерно так:

Рассматривается классическая схема:
на входе есть некий набор данных, некая последовательность шагов, скрытый от Вас черный ящик, в котором происходит, что-то неизвестное и набор выходных данных.

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

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

Отступление:
сложнее обстоит дело с «плавающими ошибками»…(не будем здесь про них).

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

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

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

Далее обобщаем результаты исследований, оставляем нужное, отсекаем лишнее и заносим новый баг в базу данных ошибок.

Тоже самое коротко:
-действительно ошибка?
-анализ и упрощение входа.
-анализ выхода
-поиск обходных путей
-оформление в базу данных ошибок.

  • 0

  • Наверх

#2

serega

Отправлено 22 сентября 2006 — 06:13

Слов много, а по сути…. :acute:

найти ошибку недостаточно. нужно ее качественно локализовать. делимся опытом:)

Тоже самое коротко:
-действительно ошибка?

Просмотр сообщения

Попробуйте занести программисту несколько раз минимую ошибку баг трекинг -моментально научитесь проверять

-анализ и упрощение входа.

Просмотр сообщения

Никто с вами и разговаривать не будет, если вы будете описывать баги нечетко — баг будет возвращаться на уточнение, пока не научитесь

-анализ выхода
-поиск обходных путей

Просмотр сообщения

У Вас всегда есть на это время?
Если вы знаете внутреннюю логику программы, то можно потратить 5 мин, иначе какой смысл

-оформление в базу данных ошибок.

Просмотр сообщения

А какой еще результат нужен от тестирования?

С моей точки зрения локализация ошибки — это способ сузить облась её поиска раработчиком, т.е. постараться максимально отсечь все лишнее в описании.
Для этого надо обладать достаточными знаниями о внутренней логике программы и уметь анализировать код. Даже в этом случае Вы не всегда сможете точно указать проблемное место, тока рекомендации.

  • 0

  • Наверх

#3

Rost

Rost

  • ФИО:Rostyslav Boruk
  • Город:Украина, Киев

Отправлено 22 сентября 2006 — 07:03

Тоже самое коротко:
-действительно ошибка?
-анализ и упрощение входа.
-анализ выхода
-поиск обходных путей
-оформление в базу данных ошибок.

Просмотр сообщения

Я согласен с serega в том, что на
«-анализ и упрощение входа.
-анализ выхода
-поиск обходных путей»
чаще всего нет времени. На самом деле это довольно редко надо делать. Вы нашли ошибку, воспроизвели ее и подробно описали. Можете двигаться дальше.

С моей точки зрения локализация ошибки — это способ сузить облась её поиска раработчиком, т.е. постараться максимально отсечь все лишнее в описании.
Для этого надо обладать достаточными знаниями о внутренней логике программы и уметь анализировать код. Даже в этом случае Вы не  всегда сможете точно указать проблемное место, тока рекомендации.

Просмотр сообщения

Согласен с максимальным отсечением. Не согласен, в данном контексте, с анализом кода. Предлагался черный ящик.

Рассматривается классическая схема:
на входе есть некий набор данных, некая последовательность шагов, скрытый от Вас черный ящик, в котором происходит, что-то неизвестное и набор выходных данных.

Просмотр сообщения

Так что грамотного детального описания (в разумных пределах) достаточно.

  • 0

Ростислав Борук,
Консультант по процессам тестирования

  • Наверх

#4

Clauster

Clauster

  • ФИО:Худобородов Валерий
  • Город:Espoo

Отправлено 22 сентября 2006 — 08:14

Это краткий пересказ какой-то книжки по тестированию или что?

  • 0

  • Наверх

#5

Rost

Rost

  • ФИО:Rostyslav Boruk
  • Город:Украина, Киев

Отправлено 22 сентября 2006 — 08:18

Это краткий пересказ какой-то книжки по тестированию или что?

Просмотр сообщения

Очень похоже на обсуждение содержания краткого пересказа основной идеи локализации и описания ошибки. :acute:

  • 0

Ростислав Борук,
Консультант по процессам тестирования

  • Наверх

#6

single player

single player

    Новый участник

  • Members
  • Pip

  • 11 сообщений

Отправлено 22 сентября 2006 — 15:13

«Это краткий пересказ какой-то книжки по тестированию или что?»
— я же написал, что основано на своем опыте, получилось книжно, потому что хотелось рассказать самое основное.
(статья была написана по просьбе руководства для начинающих тестировщиков. после каждого пункта запланирован небольшой пример непосредственно из тестирования боевых программ).

«Слов много, а по сути….»
поэтому и хотелось что бы народ поделился своим опытом.

«Попробуйте занести программисту несколько раз минимую ошибку баг трекинг -моментально научитесь проверять»
— а зачем пробовать? не лучше ли сразу научиться проверять?

«Никто с вами и разговаривать не будет, если вы будете описывать баги нечетко — баг будет возвращаться на уточнение, пока не научитесь»
— про четкое описание бага нужно говорить отдельно (если коротко, то в описании должны быть 3 вещи: последовательность шагов, наблюдаемое поведение, ожидаемое поведение). описание ошибки\локализация ошибки — это разные понятия, ИМХО.

«А какой еще результат нужен от тестирования?»
— Вы считаете, что единственным результатом тестирования, является запись об ошибке в базе?

  • 0

  • Наверх

#7

serega

Отправлено 25 сентября 2006 — 12:05

«Попробуйте занести программисту несколько раз минимую ошибку баг трекинг -моментально научитесь проверять»
— а зачем пробовать? не лучше ли сразу научиться проверять?

Просмотр сообщения

меня смущает словосочетание «научиться проверять» — мне кажется, невелика наука делать все адекватно

«Никто с вами и разговаривать не будет, если вы будете описывать баги нечетко — баг будет возвращаться на уточнение, пока не научитесь»
— про четкое описание бага нужно говорить отдельно (если коротко, то в описании должны быть 3 вещи: последовательность шагов, наблюдаемое поведение, ожидаемое поведение). описание ошибки\локализация ошибки — это разные понятия, ИМХО.

Просмотр сообщения

Вы забыли: название, версия, в которой найден, требования, ответсвенного, важность….и т.д.
Тоже будем учить? или заведем баг-трекинг?

«А какой еще результат нужен от тестирования?»
— Вы считаете, что единственным результатом тестирования, является запись об ошибке в базе?

Просмотр сообщения

Не стоит выдергивать вопрос из контекста.
Найти и зафиксировать ошибку в базу — основная задача тестирования. Кому то надо доказывать, что найденную ошбику необходимо зарегистрировать?

  • 0

  • Наверх

#8

Imbecile

Отправлено 25 сентября 2006 — 12:26

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

Просмотр сообщения

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

  • 0

In Test we trust.

  • Наверх

#9

Imbecile

Отправлено 25 сентября 2006 — 12:32

Не стоит выдергивать вопрос из контекста.
Найти и зафиксировать ошибку в базу — основная задача тестирования. Кому то надо доказывать, что найденную ошбику необходимо  зарегистрировать?

Просмотр сообщения

По поводу основной задачи тестирования:
ИМХО: Процесс тестирования является неотъемлемой частью процесса обеспечения качества (в данном случае программного продукта). Никому не нужно тестирование, если в результате этого процесса качество не изменится (улучшится). Следовательно, при процессе тестирование важно не нахождение ошибки, как таковой, а нахождение ошибок, нахождение (простите за тавтологию) которых, повлечёт изменение качества продукта (в лучшую сторону).

  • 0

In Test we trust.

  • Наверх

#10

ea_rx

ea_rx

    Новый участник

  • Members
  • Pip

  • 10 сообщений
  • ФИО:Evgeny Bartashevich

Отправлено 25 сентября 2006 — 14:16

найти ошибку недостаточно. нужно ее качественно локализовать. делимся опытом:)

я себе представляю процесс поиска возможных причин примерно так:

[..]

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

для того, чтобы не воспроизводить по памяти (а если ошибка из-за данных, введенных 20 шагов назад?), можно записывать видео с производимыми действиями.

  • 0

  • Наверх

#11

single player

single player

    Новый участник

  • Members
  • Pip

  • 11 сообщений

Отправлено 25 сентября 2006 — 14:45

«Так недолго и до того, что: «Открыл исходники и пофиксил». Понять из-за чего возникла ошибка может (в первую очередь) только программист.»
понять может только программист. мы можем только высказать свои предположения.
собственно что имелось в виду: допустим есть конечное состояние «A»(успешное выполнение) и конечное состояние «B»(ошибка). Далее представим себе, что «A» является успешным при выполнении более простых a1, a2, a3. А «B» является ошибкой, т.к. например вместо a2 мы получили х. Непосредственно проверить функцию, влиюящую на a2, мы не можем (у нас есть только доступ к функции, которая результатом которой является все «A» ), но предположить, что сбой произошел из-за того, что некорректно отработала функция, ответственная за a2, мы можем.

«ИМХО: … а нахождение ошибок, нахождение (простите за тавтологию) которых, повлечёт изменение качества продукта (в лучшую сторону).»

угу. тоже ИМХО: более качественным продукт делает нахождение ошибок и их исправление. соответственно быстрому исправлению ошибки должна помочь хорошо выполненная локализация.

2serega:
не хочется спорить и ругаться :blush: . мне не интересно как заносить ошибки в базу — интересно как их локализовывать.

  • 0

  • Наверх

#12

Rost

Rost

  • ФИО:Rostyslav Boruk
  • Город:Украина, Киев

Отправлено 25 сентября 2006 — 15:53

угу. тоже ИМХО: более качественным продукт делает нахождение ошибок и их исправление. соответственно быстрому исправлению ошибки должна помочь хорошо выполненная локализация.

Просмотр сообщения

Все правильно если Вы не тратите на локализацию пол дня. :dirol:
Если Вы тратите на локализацию больше времени чем можно просто, подробно описать ошибку, это совсем не БЫСТРОЕ исправление. Исправление в себе содержит нахождение и изменение, а не только изменение. :blush:

  • 0

Ростислав Борук,
Консультант по процессам тестирования

  • Наверх

#13

single player

single player

    Новый участник

  • Members
  • Pip

  • 11 сообщений

Отправлено 25 сентября 2006 — 16:04

«Все правильно если Вы не тратите на локализацию пол дня.»
угу :dirol: во всем нужно чувство меры.

offtopic:
для меня в работе всегда было интересно сначала поломать что-нить, а потом уже разобраться из-за чего же оно сломалось. если же тупо тестировать по сценариям, то и самому отупеть не долго :blush:

  • 0

  • Наверх

#14

Imbecile

Отправлено 26 сентября 2006 — 07:48

«ИМХО: … а нахождение ошибок, нахождение (простите за тавтологию) которых, повлечёт изменение качества продукта (в лучшую сторону).»

угу. тоже ИМХО: более качественным продукт делает нахождение ошибок и их исправление. соответственно быстрому исправлению ошибки должна помочь хорошо выполненная локализация.

Просмотр сообщения

А это уже зависит от специфики продукта. Я не спорю, что выявление дефектов и их справление — это важный процесс в достижении качества продукта, но далеко не единственный.

  • 0

In Test we trust.

  • Наверх

#15

Imbecile

Отправлено 26 сентября 2006 — 07:51

offtopic:
для меня в работе всегда было интересно сначала поломать что-нить, а потом уже разобраться из-за чего же оно сломалось. если же тупо тестировать по сценариям, то и самому отупеть не долго :good:

Просмотр сообщения

Открою страшную тайну, т-с-с-с, никому не говорите: чтобы люди не сидели и тупо не тестировали по тестовым сценариям и, следовательно, не тупели, придумали автоматизацию тестирования. Во как.

  • 0

In Test we trust.

  • Наверх

#16

Clauster

Clauster

  • ФИО:Худобородов Валерий
  • Город:Espoo

Отправлено 26 сентября 2006 — 08:14

offtopic:
для меня в работе всегда было интересно сначала поломать что-нить, а потом уже разобраться из-за чего же оно сломалось. если же тупо тестировать по сценариям, то и самому отупеть не долго :good:

Просмотр сообщения

Открою страшную тайну, т-с-с-с, никому не говорите: чтобы люди не сидели и тупо не тестировали по тестовым сценариям и, следовательно, не тупели, придумали автоматизацию тестирования. Во как.

Просмотр сообщения

В ответ открываю ещё более страшную тайну: далеко не во все проекты имеет смысл внедрять автоматизацию. :good:

  • 0

  • Наверх

#17

serega

Отправлено 26 сентября 2006 — 08:40

По поводу основной задачи тестирования:
ИМХО: Процесс тестирования является неотъемлемой частью процесса обеспечения качества (в данном случае программного продукта). Никому не нужно тестирование, если в результате этого процесса качество не изменится (улучшится). Следовательно, при процессе тестирование важно не нахождение ошибки, как таковой, а нахождение ошибок, нахождение (простите за тавтологию) которых, повлечёт изменение качества продукта (в лучшую сторону).

Просмотр сообщения

Очень толково. Только обясните мне, чем отличаются ошибки, которые влекут изменение качества продукта, от остальных ошибок?

Вы правильно заметили, что тестирование — неотъемлимая часть процесса управления качеством, в который помимо тестирования входят еще куча дисциплин.
Поэтому я считаю ошибочным вывод «Никому не нужно тестирование, если в результате этого процесса качество не изменится (улучшится).»
Тестирование может обеспечивать выполнение своих задач, но при этом хромать остальные дисциплины, начиная от управления проектов и заканчивая Help Desk

  • 0

  • Наверх

#18

serega

Отправлено 26 сентября 2006 — 08:46

2serega:
не хочется спорить и ругаться  :good: . мне не интересно как заносить ошибки в базу — интересно как их локализовывать.

Просмотр сообщения

Как локализовавать ошибки — слишком общий вопрос.
Учите преметную область и овладевайте широкими познаниями в области IT.

Пример из личного опыта. Разрабатывалась система электронной передачи документов с локальных мест в общую базу при помощи почтового сервиса.

Система состояла из 4-х модулей: локальный клиент, почтовый клиент, дешифратор со стороны сервера, парсер на центральном сервере.

Появляется ошибка — письмо не приходит, вот и локализуешь на каком сегменте произошел сбой, без знания логики всех сегментов никуда:(

  • 0

  • Наверх

#19

Rost

Rost

  • ФИО:Rostyslav Boruk
  • Город:Украина, Киев

Отправлено 26 сентября 2006 — 09:09

Поэтому я считаю ошибочным  вывод «Никому не нужно тестирование, если в результате этого процесса качество не изменится (улучшится).»
Тестирование может обеспечивать выполнение своих задач, но при этом хромать остальные дисциплины, начиная от управления проектов и заканчивая Help Desk

Просмотр сообщения

А зачем тратить ресурсы на то, что не приносит никаких изменений? Просто потому что в цепочке разработки ПО обязано быть тестирование?

  • 0

Ростислав Борук,
Консультант по процессам тестирования

  • Наверх

#20

serega

Отправлено 26 сентября 2006 — 10:37

Поэтому я считаю ошибочным  вывод «Никому не нужно тестирование, если в результате этого процесса качество не изменится (улучшится).»
Тестирование может обеспечивать выполнение своих задач, но при этом хромать остальные дисциплины, начиная от управления проектов и заканчивая Help Desk

Просмотр сообщения

А зачем тратить ресурсы на то, что не приносит никаких изменений? Просто потому что в цепочке разработки ПО обязано быть тестирование?

Просмотр сообщения

ага, и виновато тестирование.. под нож
будем строить дом, монтажные чертежи опустим — так дешевле :good:

  • 0

  • Наверх

Регистрация на курс

Плавающий баг?

Ох уж эти мистические «плавающие ошибки». Сколько вокруг них мифов! Но, когда причина найдена, всегда оказывается, что нет плавающих багов, а есть недолокализованные.

Поэтому мы будем учиться локализовывать баги, которые «не воспроизводятся». Учиться искать причину проблемы без помощи разработчика. Учиться смотреть в код и искать причину снаружи. Делить бисекционно и читать логи. В общем, всё, что нужно для воспроизведения!

Воспроизведение ошибки

Если вы не можете вопроизвести ошибку, то:

  1. Прочитайте логи — если есть доступ к логам, всегда в первую очередь смотрим туда! Если у нас веб-приложение, проверьте, что ушло с клиента на сервер.
  2. Проверьте граничные значения — баги часто тусят на границах.
  3. Попробуйте пойти «от обратного» — подумать, как получить саму проблему. Этот метод хорошо работает для багов с кэшом
  4. Составьте таблицу отличий — у вас то все работает. Что отличает ваш кейс от падающего?

Что записывать в таблицу отличий:

  1. Состояние объекта.
  2. Действия, которые с ним выполняли.
  3. Устройство, на котором воспроизводится.
  4. Время выполнения действия (какой релиз?).
  5. Способ воспроизведения (GUI, API).
  6. Количество открытых вкладок в браузере.

В отлове багов помогает понимание того, где копятся баги и какого рода: как влияет на работу системы concurrency, миграция данных, перетипизация переменной внутри кода… Зная последствия, вы будете понимать, что именно записать в таблицу отличий.

Локализация ошибки

Если вы можете воспроизвести баг, но не можете локализовать (слишком много шагов воспроизведения / слишком большой файл, внутри которого есть ошибка), то:

  1. Посмотрите код — возможно, это будет самым быстрым решением.
  2. Используйте бисекционное деление.
  3. Придумайте теорию (на баг влияет то и то) — подтвердите ее, а потом попробуйте опровергнуть.
  4. Выкиньте лишнее из шагов — возможно, именно это сбивает вас с толку

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

О курсе

Это практический курс: теории минимум. Типичная лекция — на 10-15 минут. Короткая лекция «как это применять» и тут же практика! Конечно, есть и сложные лекции (на 30 минут). Есть и короткие, на 7 минут. Нет жесткой привязки ко времени лекции. Сколько надо дать теории, столько и говорю, а дальше уже практикуйтесь.

Для локализации багов мы будем применять техники:

  • Черного ящика — как понять, что происходит, если нет доступа в код.
  • Белого ящика — куда можно посмотреть в коде? Смотреть будем на примере приложения folks с открытым исходным java-кодом. Разумеется, у вас на проекте код будет выглядеть по-другому, но зато вы получите представление, где там могут вылезти баги. Баги, которые мы будем рассматривать на курсе, не были внесены в приложение нарочно — так что все приближено к реальности.

Лекции идут в моем фирменном стиле, с картинками. Посмотрите примеры видео на моем youtube-канале, чтобы понять, подходит ли вам такой стиль изложения.

Если вы переживаете, что не сможете что-то сделать (например, задания на просмотр кода), вот вам задача для самопроверки — соберите проект folks и запустите тесты. Инструкция есть, есть даже видео-инструкция по установке java, maven на Windows, Если справитесь, то и все остальное будет вам по плечу!

Программа курса

0. Введение

Что такое локализация и зачем она вообще нужна тестировщику.

Как умение локализовывать задачи экономит время команды и убирает панику.

Как знание о типовых проблемах помогает воспроизводить баги, которые «не воспроизводятся».

1. Уточнение устройств, на которых есть баг

На что обращать внимание при багах «поехала верстка», «текст вылезает за пределы экрана».

Как понять, в какой момент едет верстка? Какие инструменты использовать:

— как замерить размер окна;
— какие есть линейки;
— как посмотреть размер окна в консоли.

2. Исследование состояний

Изучим разные состояния объекта. Если проблема при сохранении — а кого мы вообще сохраняем?

— свежесозданную карточку
— отредактированную
— удаленную

Если у нас есть пользователь, то какой он? А как регистрировался? Как это может повлиять на воспроизведение бага?

3. Использование классов эквивалентности и граничных значений

Что такое классы эквивалентности.

Почему на границах встречаются баги.

Зачем тестировать ноль и как его найти, если у нас не строка ввода?

4. Опровержение своих теорий

Как опровергать свои теории и зачем это нужно.

— таблица отличий;

— метод «найди 5 отличий»;

— принцип минимализма (отсеивание лишнего).

5. Метод бисекционного деления

Что такое бисекционное деление.

Как его использовать тестировщику для локализации бага.

Как оно используется в разработке и к каким проблемам может привести.

6. Чтение логов

Что такое логи. Что в них записывается?

Как читать логи. Как читать стектрейс ошибки.

Логи на сервере и на клиенте.

7. Просмотр запросов с клиента на сервер

На клиенте помимо JS-логов можно смотреть, что вообще ушло на сервер.

Это помогает понять, где произошла ошибка и кто виноват: клиент или сервер. Учимся это делать.

8. Воспроизведение «от обратного»

Техника расследования закрытой комнаты. Наиболее актуальна для багов с кэшом.

Вот есть баг, из кэша достаются неправильные данные. Как воспроизвести? Идем от обратного, пытаемся получить “плохие данные” разными путями.

9. Проверка по коду

Как читать код, при условии, что разработчики идут вам на встречу и разделяют потроха логики и описание объектов.

Читаем java-объект и схему создания БД. Выверяем их на соответствие друг другу.

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

10. Проверка соответствия типов данных

Если поле встречается в коде несколько раз:

— в объектной модели;

— в схеме создания БД;

— где-то еще

Важно проверять соответствие типов. Смотрим, какие встречаются баги на несоответствие типов.

11. Проверка стыка интеграции

Какая бывает интеграция между системами.

Какие бывают баги на стыке интеграции.

Куда смотреть в первую очередь.

12. Проверка данных после миграции

Зачем тестировщику нужна как чистая база, так и база, живущая веками?

Примеры ошибок, вылезающих после миграции и почему они не ловятся на свежей тестовой БД.

13. Проверка concurrency

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

Но о concurrency важно знать, так как параллельная работа может быть и на другом уровне:

  • Идет забор данных из базы по 1000 записей за раз. Что, если в этой 1000 встретились 2 одинаковых клиента? Строка базы заблокирована первым изменением — второе разваливается.
  • Интеграция по SOAP \ REST. Если запросов много, там тоже можно влететь на изменение одного и того же клиента.

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

14. Заключение

Подводим итоги.

Вопросы и ответы

1. Можно ли проходить курс на Linux или Mac?

Да, он не зависит от вашей OS

2. Какие знания нужны для курса?

Общие знания о тестировании — что это вообще такое, как составлять тесты, что такое классы эквивалентности.

Если будете делать ДЗ с просмотром кода (необязательные), то:

  • Базовое понимание языка программирования (любого) — вы не должны падать в обморок от слов string или «тип данных». Но все, что будет нужно для ДЗ, я объясню.
  • Умение устанавливать новые программы — мы будем смотреть в код, а для этого нужно будет установить java, mercurial, maven. Вот инструкция, соберите проект перед записью на курс.

3. Будет ли мне интересно, если я проходил другие ваши курсы?

Если вы прошли «Школу для начинающих тестировщиков» в группе, то встречались с багами в коде folks — но эти задания на курсе необязательные! Так что сильно не влияют на интерес.

Если вы прошли «Логи как инструмент тестировщика», то уже сделали пару обязательных заданий. Но всё равно будет много нового и полезного

4. А скидку то дадут мне за эти ДЗ?

Да, покажите ваш сертификат и получите скидку:

  • Логи как инструмент тестировщика → 20%
  • Школа для начинающих, пройденная в группе → 10%

Как записаться

Регистрация и дата ближайшего запуска

Способы оплаты

7.1. Способы локализации

После
того, как с помощью контрольных тестов
(или каким либо другим путем) установлено,
что в программе или в конкретном ее
блоке имеется ошибка, возникает задача
ее локализации, то есть установления
точного места в программе, где находится
ошибка.

Процесс
локализации ошибок состоит из следующих
трех компонент:

1.
Получение на машине тестовых результатов.

2.
Анализ тестовых результатов и сверка
их с эталонными.

3.
Выявление ошибки или формулировка
предположения о характере и месте ошибки
в программе.

По
принципам работы средства локализации
разделяются на 4 типа :

1.
Аварийная печать.

2.
Печать в узлах.

3.
Слежение.

4.
Прокрутка.

АВАРИЙНАЯ
ПЕЧАТЬ

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

ПЕЧАТЬ
В УЗЛАХ

включается в работу в выбранных
программистом местах программы; после
осуществления печати значений данных
переменных продолжается выполнение
отлаживаемой программы.

СЛЕЖЕНИЕ
производится или по всей программе, или
на заданном программистом участке.
Причем слежение может осуществляться
как за переменными (арифметическое
слежение), так и за операторами (логическое
слежение). Если обнаруживается, что
происходит присваивание заданной
переменной или выполнение оператора с
заданной меткой, то производится печать
имени переменной или метки и выполнение
программы продолжается. Отличием от
печати в узлах является то, что место
печати может точно и не определяться
программистом (для арифметического
слежения); отличается также и содержание
печати.

ПРОКРУТКА
производится на заданных участках
программы, и после выполнения каждого
оператора заданного типа (например,
присваивания или помеченного) происходит
отладочная печать.

По
типам печатаемых значений (числовые и
текстовые или меточные) средства
разделяются на арифметические и
логические.

7.2. Классификация средств локализации ошибок

Ниже
дана классификация средств локализации.

ТИПЫ
СРЕДСТВ ЛОКАЛИЗАЦИИ ОШИБОК :

1.
Языковые.

1.1.
Обычные.

1.2.
Специальные.

2.
Системные.

(3.
Пакетные)

СРЕДСТВА
ЛОКАЛИЗАЦИИ:

1.
Аварийная печать (арифметическая).

1.1.
Специальные средства языка.

1.2.
Системные средства.

2.
Печать в узлах (арифметическая).

2.1.
Обычные средства языка.

2.2.
Специальные средства языка.

3.
Слежение (специальные средства).

3.1.
Арифметическое.

3.2.
Логическое.

4.
Прокрутка (специальные средства).

4.1.
Арифметическая.

4.2.
Логическая.

8. Технология отладки программы автоматизации учета движения товаров на складе малого предприятия

При
отладке программы использовались
следующие методы контроля и локализации
ошибок (обзор методов см. в теоретической
части раздела) :

1.
Просмотр текста программы и прокрутка
с целью обнаружения явных синтаксических
и логических ошибок.

2.
Трансляция программы (транслятор выдает
сообщения об обнаруженных им ошибках
в тексте программы).

3.
Тестирование.
Тестирование
проводилось посредством ввода исходных
данных, с дальнейшей их обработкой,
выводом результатов на печать и экран.
Результаты работы программы сравнивались
заданными в техническом задании.

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

Отладка
программы производилась по следующему
алгоритму :

1.
Прогонка программы с набором тестовых
входных данных и выявление наличия
ошибок.

2.
Выделение области программы, в которой
может находиться ошибка. Просмотр
листинга программы с целью возможного
визуального обнаружения ошибок. В
противном случае — установка контрольной
точки примерно в середине выделенной
области.

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

4.
Если контрольная точка программы была
обработана, то далее следует изучение
значений регистров, переменных и
параметров программы с тем, чтобы
убедиться в их правильности. При появлении
ошибки — новый перенос контрольной точки
и возврат к шагу 2.

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

В
качестве тестовых входных данных
использовалась последовательность
частотных выборок, генерируемых
имитатором в режиме 1. (Каждому интервалу
соответствует фиксированное значение
выборок.)

Соседние файлы в папке 4Diplom

  • #

    16.04.201332.77 Кб9A4.vsd

  • #
  • #
  • #
  • #
  • #

Понравилась статья? Поделить с друзьями:
  • Как классифицируются виды ошибок
  • Как исправлять лексические ошибки
  • Как исправляются нотариальные ошибки
  • Как исправлять ошибки на фикбуке
  • Как исправлять ошибки на сайте