Зачем нужен mix и как он работает
Часть 1: Зачем нужен mix и как он работает?
Что такое mix?
mix — это инструмент сборки и управления проектами в экосистеме Elixir (аналог npm в Node.js, cargo в Rust, lein в Clojure).
Он входит в поставку Elixir и отвечает за:
| Функция | Описание |
| Создание проектов | mix new my_app — генерирует структуру проекта |
| ⚙️ Зависимости | mix deps.get, mix deps.compile — управление библиотеками из Hex |
| Тестирование | mix test — запуск тестов через ExUnit |
| Компиляция | mix compile — компиляция .ex → .beam |
| Задачи | Создание собственных задач (mix run, mix phx.server, etc.) |
| Конфигурация | config/, mix.exs — центр управления проектом |
Как создаётся проект с помощью mix?
1. Создание нового проекта
☯
Terminal:
⌕
≡
✕
mix new my_app --sup
Флаг --sup добавляет супервизор (полезно для OTP-приложений, но можно и без него).
2. Сгенерированная структура:
☯
Terminal:
⌕
≡
✕
my_app/ ├── config/ │ └── config.exs # настройки проекта ├── lib/ │ └── my_app.ex # основной модуль │ └── my_app/ # (если указать --module MyApp.Submodule — создаются подкаталоги) ├── test/ │ ├── test_helper.exs # загрузка ExUnit и setup │ └── my_app_test.exs # пример теста ├── .formatter.exs # правила форматирования ├── mix.exs # ✅ главный конфиг проекта (зависимости, приложения, версия) └── README.md
3. Файл `mix.exs` — "сердце проекта":
☯
Terminal:
⌕
≡
✕
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
app: :my_app,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Зависимости
defp deps do
[
# {:plug, "~> 1.14"}
]
end
end4. Файл `test/test_helper.exs`:
☯
Terminal:
⌕
≡
✕
ExUnit.start() # <-- обязательная инициализация тестового фреймворка
5. Пример теста (`test/my_app_test.exs`):
☯
Terminal:
⌕
≡
✕
defmodule MyAppTest do
use ExUnit.Case
doctest MyApp
test "greets the world" do
assert MyApp.hello() == :world
end
enduse ExUnit.Case подключает макросы test, assert, refute, setup и др.
6. Запуск тестов:
☯
Terminal:
⌕
≡
✕
# Все тесты mix test # Один файл mix test test/my_app_test.exs # Один конкретный тест (по строке) mix test test/my_app_test.exs:5 # С подробным логом mix test --trace # С покрытием (coverage) mix test --cover
Часть 2: Как создать проект *без* mix?
Да, можно — но это ручной, low-level способ, как писать на "голом" Elixir. Чаще используется для:
- скриптов,
- обучения,
- мини-экспериментов,
- embedded-сценариев (например, в Nerves).
Шаг 1: Создайте структуру вручную
☯
Terminal:
⌕
≡
✕
mkdir my_script && cd my_script mkdir -p lib test touch lib/math.ex test/math_test.exs
Структура:
☯
Terminal:
⌕
≡
✕
my_script/
├── lib/
│ └── math.ex
└── test/
└── math_test.exsШаг 2: Напишите модуль (`lib/math.ex`)
☯
Terminal:
⌕
≡
✕
defmodule Math do def add(a, b), do: a + b def multiply(a, b), do: a * b end
Шаг 3: Напишите тест (`test/math_test.exs`)
⚠️ ВАЖНО: без mix нет автоматической загрузки test_helper.exs, поэтому нужно вручную инициализировать ExUnit:
☯
Terminal:
⌕
≡
✕
# test/math_test.exs
ExUnit.start() # ← обязателен при запуске вручную!
defmodule MathTest do
use ExUnit.Case
test "add/2 works" do
assert Math.add(2, 3) == 5
end
test "multiply/2 works" do
assert Math.multiply(4, 5) == 20
end
end> ❗ Обратите внимание:
> - Это файл .exs (script), а не .ex — он компилируется при каждом запуске, а не кэшируется.
> - ExUnit.start() должен быть выполнен до определения тестов.
Шаг 4: Запуск тестов *без mix*
☯
Terminal:
⌕
≡
✕
# Запускаем напрямую через `elixir`, указывая пути к коду elixir -r lib/math.ex -r test/math_test.exs
✅ Вывод:
☯
Terminal:
⌕
≡
✕
.. Finished in 0.03 seconds 2 tests, 0 failures
> ⚠️ Минусы такого подхода:
> - Нет автоматического поиска всех тестов в папке.
> - Нужно вручную указывать каждый файл через -r.
> - Нет удобных флагов (--trace, --cover, фильтрация по тегам и т.д.).
> - Нет поддержки зависимостей (deps), конфигов, сборки релизов и т.п.
Часть 3: Можно ли писать тесты *внутри модулей*?
Да, технически можно, но это не рекомендуется согласно best practices (тесты должны быть отделены от production-кода), но для демонстрации — вот как:
✅ Способ: тесты внутри `.exs` (скрипта), но *возле* модуля
Создайте файл math_with_tests.exs:
☯
Terminal:
⌕
≡
✕
# math_with_tests.exs
defmodule Math do
def add(a, b), do: a + b
end
# ↓ Тесты прямо в том же файле (но это .exs!)
ExUnit.start(auto_run: false) # отключаем автозапуск
defmodule MathTest do
use ExUnit.Case, async: false
test "add/2" do
assert Math.add(1, 2) == 3
end
end
# Явно запускаем тесты в конце
ExUnit.run()Запуск:
☯
Terminal:
⌕
≡
✕
elixir math_with_tests.exs
✅ Работает!
❌ Почему так делать **не стоит**:
| Проблема | Объяснение |
| Загрязнение кода | Production-код и тесты в одном месте — нарушает разделение ответственности |
| Производительность | Тесты могут замедлять компиляцию/запуск основного приложения |
| Нет CI-интеграции | Инструменты вроде GitHub Actions ожидают mix test |
| Зависимости | :ex_unit — только для :test, в production он не нужен (only: :test в mix.exs) |
| Структура | Нарушается стандартная структура lib/ и test/, которую ожидают все инструменты |
> ✅ Правильный путь:
> - Код — в lib/ → .ex
> - Тесты — в test/ → .exs, с use ExUnit.Case
> - Запуск — через mix test
Краткое резюме
| Вопрос | Ответ |
Что такое mix? | Система сборки и управления проектами в Elixir — обязательный инструмент для реальных проектов. |
| Как создать проект? | mix new имя_проекта [--sup] → создаёт mix.exs, lib/, test/, config/. |
| Как запустить тесты? | mix test → находит всё в test/, запускает через ExUnit. |
Можно ли без mix? | Да, но вручную: elixir -r lib/mod.ex -r test/mod_test.exs, с ExUnit.start() в коде. |
| Тесты внутри модуля? | Технически — да (в .exs), но не следует так делать в production-коде. |
-
Создано 19.11.2025 07:33:15
-
Roman Sakhno

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.