Журнал / Польза

Автоматизируй это! Упрощаем жизнь разработчика

Как автоматизировать тестирование, cбор и обработку данных, деплой — и другие рутинные задачи.

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

Конечно, автоматизация нужна не всегда. Например, если сделать что-то нужно один раз, то лучше сделать это руками — не стоит пять часов писать скрипт ради того, чтобы решить одну пятиминутную задачу. Но если задача объемная или часто повторяется, то её нужно автоматизировать.

В этой статье вместе с курсом Яндекс.Практикума «Мидл Python-разработчик» мы разберёмся, какие готовые инструменты или библиотеки можно использовать для автоматизации рутинных задач. Использовать будем Python: потому что он позволяет быстро написать рабочий код, и для него существует много разных библиотек.

Тестирование

Тестировать вручную — не лучшая привычка. Вы можете что-то пропустить или забыть. Часто случается так, что вы протестировали фичу А и исправили в ней все баги, а потом сделали то же самое с фичей Б. Сколько людей вернутся к фиче А, чтобы проверить, не пошло ли что-нибудь не так? А если таких фич несколько сотен?

Поэтому лучше начать автоматизировать тестирование как можно раньше. Отдельные функции можно проверять с помощью Unit-тестов.

Unit-тесты (модульные тесты) — это тесты, которые позволяют проверять отдельные блоки на корректность работы. Обычно в Unit-тест передаются метод, параметры и ожидаемый результат.

Например, есть функция sum(), которая складывает два числа. Для этой функции пишутся тесты, которые проверяют, как сработает функция, если ввести:

1. два положительных числа;

2. два отрицательных числа;

3. два нуля;

4. положительное число и None;

5. число и строку.

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

В Python для этого используется модуль unittest. Допустим, у нас есть файл app.py вот с такими функциями:

def sum(a, b):
   return a + b
 
 
def sum_array(nums):
   s = 0
   for num in nums:
       s += num
   return s

Чтобы их проверить, мы создаём файл tests.py:

# Импортируем наш файл и библиотеку с тестами
import app
import unittest
 
# Создаём класс с тестами
class TestSumMethods(unittest.TestCase):
 
   # Один метод — один тест
   def test_sum_positive(self):
       # Метод assertEqual() проверяет, сходится ли результат функции с предполагаемым результатом
       self.assertEqual(app.sum(1, 2), 5)
 
   def test_sum_negative(self):
       # Здесь намеренно допущена ошибка
       self.assertEqual(app.sum(-2, -5), -5)
 
   def test_sum_array(self):
       self.assertEqual(app.sum_array([1, 2, 3, 4, 5]), 15)
 
# Запускаем тесты
if __name__ == '__main__':
   unittest.main()

Запустив код, мы увидим, сколько времени потребовалось на тесты, и где была допущена ошибка:

87

Если нужно протестировать интерфейс сайта, то можно воспользоваться другой библиотекой — Selenium. Она позволяет имитировать действия пользователя в браузере: кликать, печатать, скроллить и так далее.

Она не входит в состав предустановленных библиотек Python, поэтому её нужно будет установить с помощью команды: pip install selenium. Подробные инструкции по установке можно найти на PyPi.

#!/usr/bin/env python3
 
# Импортируем необходимые модули
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
 
# Открываем браузер
driver = webdriver.Chrome()
 
# Переходим по ссылке
driver.get('https://yandex.ru')
# Находим на странице поле ввода поискового запроса
search_bar = driver.find_element_by_name('text')
 
# Очищаем поле
search_bar.clear()
# Вводим запрос
search_bar.send_keys('Практикум')
# Имитируем нажатие кнопки Enter
search_bar.send_keys(Keys.RETURN)
 
# Получаем код страницы
body = driver.find_element_by_tag_name('body')
html = body.get_attribute('innerHTML')
 
# Проверяем, есть ли в тексте страницы нужная нам строка
try:
   assert 'Яндекс.Практикум' in html
   print('Практикум найден!')
except:
   print('Практикум не найден :(')
 
# Закрываем браузер
driver.quit()

То же самое можно сделать и с десктопными приложениями — для этого понадобится библиотека Pynput.

Деплой

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

Автоматизировать деплой можно при помощи Git. Он позволяет отправлять файлы не только на GitHub, но и на свой сервер. На сервере вам нужно будет создать специальный bare-репозиторий, а на локальном компьютере указать доступ к нему.

Bare-репозиторий — это репозиторий, в котором хранится только актуальная версия кода.

Дальше вы можете создать на сервере скрипты, которые будут вызываться при определённых условиях. Например, если вы отправили на сервер новую версию сайта на Django (Python-фреймворк для разработки веб-приложений) и вам нужно её запустить. Тогда вы напишете скрипт, который вызывается после получения новых файлов.

Если всё настроено правильно, то вы сможете деплоить приложения на сервер с помощью всего одной команды в терминале. Но это тема для отдельной большой статьи о DevOps.

Мониторинг

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

Для решения этих задач можно найти готовые скрипты или специальные сервисы. Например, для мониторинга состояния сайта есть сервисы вроде Zabbix или WebSitePulse. Но если вы хотите самостоятельно заниматься проверкой, то можно воспользоваться Selenium, о которой мы писали раньше, или стандартной библиотекой requests.

#!/usr/bin/env python
import os
import requests
import time
 
# Адрес сайта, который будем проверять
SITE = 'https://yandex.ru/'
# Интервал проверок в секундах 
# 60 * 60 = 3600 секунд = 1 час
INTERVAL = 60 * 60
# Какие сообщения будет выдавать скрипт во время работы
OK_MESSAGE = 'Site is up'
ERROR_MESSAGE = 'Site is down'
 
 
# Функция проверки
def check():
   # Отправляем запрос на сайт
   try:
       r = requests.get(SITE)
 
       # Статус 200 означает, что с сайтом всё хорощо
       # Поэтому возвращаем True, если попался он
       if r.status_code == 200:
           return True
 
       # Если статус другой, то возвращаем False
       return False
   except:
       # Если до сайта не удалось достучаться, то возвращаем False
       return False
 
 
# Запускаем цикл проверок
while True:
   # Проверяем сайт
   r = check()
  
   # Выводим сообщение о результате работы сайта
   # Тут мы отправляем уведомления с помощью оболочки рабочего стола Gnome для Linux
   # Но можно сделать что угодно — послать сообщение в мессенджере, просто записать вывод в консоль и так далее
   if(r):
       os.system('notify-send \'{}\''.format(OK_MESSAGE))
   else:
       os.system('notify-send \'{}\''.format(ERROR_MESSAGE))
 
   # Ждём перед следующей проверкой
   time.sleep(INTERVAL)

Этот скрипт можно дополнить для своих рабочих задач — например, чтобы проверять, какой текст на странице и так далее.

Сбор и обработка данных

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

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

Если же у сервиса нет своего API, то можно получить данные с помощью уже знакомых нам инструментов — Selenium или requests. А для удобной обработки можно воспользоваться библиотекой BeautifulSoup.

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

# Подключаем библиотеки
import requests
from bs4 import BeautifulSoup
 
# Отправляем поисковый запрос на сервер
query = 'Практикум'
r = requests.get('https://yandex.ru/search/?text={}'.format(query))
# Создаём суп
soup = BeautifulSoup(r.text, 'html.parser')
 
# Находим все элементы из поисковой выдачи
results = soup.find_all(class_='serp-item')
 
# Выводим результат
for i, result in enumerate(results):
   title = result.find(class_='organic__url-text')
   print(f'{i}. {title.get_text()}')

87

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

Разработчик может использовать скрипты и для работы с данными: например, чтобы проверить валидность JSON, перевести CSV в XML и так далее.

Другие рутинные задачи

Подумайте, какие задачи вы решаете на работе чаще всего. Может быть, вам нужно каждый день выполнять какие-то действия на сервере? Или вы вручную переносите данные и правите конфигурации?

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