Перейти к содержанию

Тестирование, GUI и конкурентность

Краткий справочник по вопросам тестирования кода, оконных приложений и параллельных вычислений в Python и Go.

1. Тестирование: модульное, функциональное, приёмочное; пирамида тестов; pytest и testing

Модульное (unit) тестирование проверяет отдельную функцию или метод в изоляции, функциональное — поведение фичи целиком (часто через её внешний интерфейс), а приёмочное (acceptance) — соответствие системы требованиям заказчика, обычно с точки зрения пользователя. Пирамида тестов рекомендует держать много быстрых unit-тестов в основании, меньше интеграционных в середине и совсем немного медленных end-to-end сверху. В Python стандартом де-факто стал pytest (тесты — обычные функции test_* с assert), в Go тесты пишут через встроенный пакет testing (функции func TestXxx(t *testing.T)).

def test_add():
    assert add(2, 3) == 5
func TestAdd(t *testing.T) {
    if got := Add(2, 3); got != 5 {
        t.Errorf("Add(2,3) = %d; want 5", got)
    }
}

2. Создание оконных приложений: GUI, Tkinter и PyQt, Fyne; цикл событий и виджеты

GUI (графический интерфейс) строится из виджетов — кнопок, полей ввода, меток — которые размещаются в окне и реагируют на действия пользователя. В основе любого GUI лежит цикл событий (event loop): программа ждёт события (клик, нажатие клавиши) и вызывает привязанный к нему обработчик (callback). В Python для этого используют Tkinter (входит в стандартную библиотеку, прост для старта) и PyQt (мощный, на базе Qt, со сложным API), в Go популярна кроссплатформенная библиотека Fyne.

import tkinter as tk
root = tk.Tk()
tk.Button(root, text="OK", command=lambda: print("click")).pack()
root.mainloop()  # запуск цикла событий

3. Параллельные вычисления: конкурентность vs параллелизм; asyncio и потоки, горутины и каналы

Конкурентность — это способ структурировать программу так, чтобы несколько задач выполнялись с чередованием (даже на одном ядре), а параллелизм — их одновременное выполнение на нескольких ядрах. В Python конкурентность дают потоки (threading, но из-за GIL реального параллелизма CPU-нагрузки нет) и asyncio (кооперативная многозадачность через async/await и единый event loop), а для параллелизма по CPU берут процессы (multiprocessing). В Go конкурентность встроена в язык: лёгкие горутины (go f()) общаются через каналы (chan), реализуя принцип «не передавай память через коммуникацию — общайся, передавая данные».

ch := make(chan int)
go func() { ch <- 42 }()  // горутина шлёт значение
fmt.Println(<-ch)          // основной поток получает

См. также