Token导航 LogoToken导航

Agent Skill · 开发

elixir-tdd(Elixir TDD 命令行)

elixir-tdd 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

elixir-tdd 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 17,352。

总安装 419周安装 18GitHub Stars 公开资料未说明下载 147核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:elixir-tdd(Elixir TDD 命令行)
来源仓库:https://github.com/hwatkins/my-skills
仓库路径:skills/elixir-tdd
安装命令:
npx skills add https://github.com/hwatkins/my-skills --skill elixir-tdd
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/hwatkins/my-skills --skill elixir-tdd

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

elixir-tdd 强制执行测试驱动开发流程,要求每项改动均以失败测试开始。适用于在 Codex、Claude、Cursor、Gemini CLI 中确保 Elixir 与 Phoenix 项目的测试覆盖率。遵循红-绿-重构循环,使用 ExUnit 编写行为描述清晰的测试用例。

安装前请确认项目已配置 test 脚本,并准备好夹具工厂与外部依赖 mocking 方案。elixir-tdd 属于开发类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/elixir-tdd

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/hwatkins/my-skills --skill elixir-tdd;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

elixir-tdd 怎么安装?

在终端执行 npx skills add https://github.com/hwatkins/my-skills --skill elixir-tdd。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

elixir-tdd 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

elixir-tdd 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

elixir-tdd 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

elixir-tdd 用的人多吗?

公开数据是累计安装 419 次,近一周安装 18 次,下载 147 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

elixir-tdd 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
elixir-tdd

Elixir TDD 命令行 · 本页

419—需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Elixir TDD Enforcement

Strict test-driven development practices for Elixir and Phoenix projects.

The Golden Rule

No Code Without a Failing Test First

This is not optional. This is not negotiable. Every feature, every bug fix, every change starts with a test.

The TDD Cycle

  1. Red: Write a test that describes the behavior you want. Run it. It must fail.
  2. Green: Write the minimum code to make the test pass. Nothing more.
  3. Refactor: Clean up while keeping tests green.
  4. Repeat
# Step 1: Write the failing test
test "create_user/1 with valid attrs creates a user" do
  attrs = %{email: "test@example.com", name: "Test User"}
  assert {:ok, %User{} = user} = Accounts.create_user(attrs)
  assert user.email == "test@example.com"
end

# Step 2: Run it - it MUST fail
# $ mix test test/my_app/accounts_test.exs:10
# ** (UndefinedFunctionError) function Accounts.create_user/1 is undefined

# Step 3: Write minimum code to pass
def create_user(attrs) do
  %User{}
  |> User.changeset(attrs)
  |> Repo.insert()
end

# Step 4: Run test again - it passes
# Step 5: Refactor if needed, keeping tests green

Test File Structure

Match your source structure:

lib/my_app/accounts/user.ex      → test/my_app/accounts/user_test.exs
lib/my_app/accounts.ex           → test/my_app/accounts_test.exs
lib/my_app_web/live/task_live.ex → test/my_app_web/live/task_live_test.exs
lib/my_app_web/controllers/      → test/my_app_web/controllers/

Mandatory Test Cases

For every function, test:

1. Happy Path

Valid input produces expected output.

test "create_task/1 with valid attrs creates task" do
  attrs = %{title: "Test Task", status: :todo}
  assert {:ok, %Task{} = task} = Tasks.create_task(attrs)
  assert task.title == "Test Task"
  assert task.status == :todo
end

2. Validation Failures

Invalid input returns error changeset.

test "create_task/1 with missing title returns error" do
  assert {:error, %Ecto.Changeset{} = changeset} = Tasks.create_task(%{})
  assert %{title: ["can't be blank"]} = errors_on(changeset)
end

test "create_task/1 with invalid status returns error" do
  attrs = %{title: "Test", status: :invalid_status}
  assert {:error, changeset} = Tasks.create_task(attrs)
  assert %{status: ["is invalid"]} = errors_on(changeset)
end

3. Edge Cases

Boundary conditions and unusual inputs.

test "create_task/1 with empty string title returns error" do
  assert {:error, changeset} = Tasks.create_task(%{title: ""})
  assert %{title: ["can't be blank"]} = errors_on(changeset)
end

test "create_task/1 with whitespace-only title returns error" do
  assert {:error, changeset} = Tasks.create_task(%{title: "   "})
  assert %{title: ["can't be blank"]} = errors_on(changeset)
end

test "list_tasks/0 returns empty list when no tasks exist" do
  assert [] = Tasks.list_tasks()
end

4. Authorization

Users can only access their own resources.

test "get_task/2 returns error when task belongs to another user" do
  other_user = user_fixture()
  task = task_fixture(user_id: other_user.id)
  user = user_fixture()

  assert {:error, :not_found} = Tasks.get_task(user, task.id)
end

test "update_task/3 returns error when user doesn't own task" do
  owner = user_fixture()
  other_user = user_fixture()
  task = task_fixture(user_id: owner.id)

  assert {:error, :unauthorized} = Tasks.update_task(other_user, task, %{title: "Hacked"})
end

5. State Transitions (if applicable)

Valid and invalid state changes.

describe "transition_task/2" do
  test "allows todo -> in_progress" do
    task = task_fixture(status: :todo)
    assert {:ok, task} = Tasks.transition_task(task, :in_progress)
    assert task.status == :in_progress
  end

  test "allows in_progress -> done" do
    task = task_fixture(status: :in_progress)
    assert {:ok, task} = Tasks.transition_task(task, :done)
    assert task.status == :done
  end

  test "rejects todo -> done (must go through in_progress)" do
    task = task_fixture(status: :todo)
    assert {:error, :invalid_transition} = Tasks.transition_task(task, :done)
  end

  test "rejects done -> todo" do
    task = task_fixture(status: :done)
    assert {:error, :invalid_transition} = Tasks.transition_task(task, :todo)
  end
end

Testing LiveView

Use Phoenix.LiveViewTest for integration tests.

import Phoenix.LiveViewTest

describe "TaskLive.Index" do
  test "renders task list", %{conn: conn} do
    task = task_fixture(title: "My Task")
    {:ok, view, html} = live(conn, ~p"/tasks")

    assert html =~ "My Task"
    assert has_element?(view, "#task-#{task.id}")
  end

  test "creates new task", %{conn: conn} do
    {:ok, view, _html} = live(conn, ~p"/tasks")

    view
    |> form("#task-form", task: %{title: "New Task"})
    |> render_submit()

    assert has_element?(view, "#tasks", "New Task")
  end

  test "validates task on change", %{conn: conn} do
    {:ok, view, _html} = live(conn, ~p"/tasks/new")

    html =
      view
      |> form("#task-form", task: %{title: ""})
      |> render_change()

    assert html =~ "can't be blank"
  end

  test "deletes task", %{conn: conn} do
    task = task_fixture(title: "Delete Me")
    {:ok, view, _html} = live(conn, ~p"/tasks")

    view
    |> element("#task-#{task.id} button", "Delete")
    |> render_click()

    refute has_element?(view, "#task-#{task.id}")
  end
end

Test Data

Use factories or fixture functions. Keep them minimal.

# test/support/fixtures/accounts_fixtures.ex
defmodule MyApp.AccountsFixtures do
  def user_fixture(attrs \\ %{}) do
    {:ok, user} =
      attrs
      |> Enum.into(%{
        email: "user#{System.unique_integer()}@example.com",
        name: "Test User"
      })
      |> MyApp.Accounts.create_user()

    user
  end
end

# Or with ExMachina
defmodule MyApp.Factory do
  use ExMachina.Ecto, repo: MyApp.Repo

  def user_factory do
    %MyApp.Accounts.User{
      email: sequence(:email, &"user#{&1}@example.com"),
      name: "Test User"
    }
  end
end

What NOT to Do

❌ Don't write tests after the code

# WRONG: Code first, then tests
def create_task(attrs), do: ...  # Written first
test "create_task works" do ...  # Added later to "cover" it

❌ Don't skip tests for "simple" functions

# WRONG: "It's too simple to test"
def full_name(user), do: "#{user.first_name} #{user.last_name}"
# Still needs tests! What if first_name is nil?

❌ Don't test private functions directly

# WRONG: Testing private implementation
test "parse_date/1 parses ISO format" do
  assert MyModule.parse_date("2024-01-01") == ~D[2024-01-01]
end

# RIGHT: Test through the public API
test "create_event/1 accepts ISO date strings" do
  assert {:ok, event} = Events.create_event(%{date: "2024-01-01"})
  assert event.date == ~D[2024-01-01]
end

❌ Don't mock Ecto or database in context tests

# WRONG: Mocking the repo
expect(Repo, :insert, fn _ -> {:ok, %User{}} end)

# RIGHT: Use the sandbox, test real behavior
assert {:ok, %User{}} = Accounts.create_user(valid_attrs)
assert Repo.get(User, user.id)  # Actually in database

❌ Don't write tests that pass regardless of implementation

# WRONG: Test always passes
test "does something" do
  result = MyModule.do_thing()
  assert result  # What if result is {:error, ...}? Still truthy!
end

# RIGHT: Assert specific expectations
test "returns ok tuple with user" do
  assert {:ok, %User{email: "test@example.com"}} = MyModule.do_thing()
end

Pre-Implementation Checklist

Before writing ANY code, ask yourself:

  1. ☐ Have I written a failing test?
  2. ☐ Does the test describe the behavior I want?
  3. ☐ Have I run the test and confirmed it fails?
  4. ☐ Does it fail for the RIGHT reason?

Only after checking all boxes: write the implementation.

Test Organization

defmodule MyApp.TasksTest do
  use MyApp.DataCase

  alias MyApp.Tasks
  alias MyApp.Tasks.Task

  import MyApp.AccountsFixtures
  import MyApp.TasksFixtures

  describe "create_task/1" do
    test "with valid attrs creates task" do
      # ...
    end

    test "with invalid attrs returns error changeset" do
      # ...
    end

    test "with empty title returns error" do
      # ...
    end
  end

  describe "update_task/2" do
    setup do
      task = task_fixture()
      %{task: task}
    end

    test "with valid attrs updates the task", %{task: task} do
      # ...
    end
  end

  describe "delete_task/1" do
    # ...
  end
end

Mocking External Dependencies with Mox

Use behaviours + Mox for external services. Never mock Ecto or internal modules.

# 1. Define a behaviour
defmodule MyApp.WeatherAPI do
  @callback get_forecast(String.t()) :: {:ok, map()} | {:error, term()}
end

# 2. Create the real implementation
defmodule MyApp.WeatherAPI.Client do
  @behaviour MyApp.WeatherAPI

  @impl true
  def get_forecast(city) do
    Req.get("https://api.weather.com/forecast", params: [city: city])
  end
end

# 3. Configure the mock in test_helper.exs
Mox.defmock(MyApp.MockWeatherAPI, for: MyApp.WeatherAPI)

# 4. Configure in config/test.exs
# config :my_app, weather_api: MyApp.MockWeatherAPI

# 5. Use in your context (reads from config)
defmodule MyApp.Weather do
  def weather_api, do: Application.get_env(:my_app, :weather_api, MyApp.WeatherAPI.Client)

  def get_forecast(city) do
    weather_api().get_forecast(city)
  end
end

# 6. Test with mock
import Mox

test "get_forecast returns weather data" do
  expect(MyApp.MockWeatherAPI, :get_forecast, fn "London" ->
    {:ok, %{temp: 15, condition: "cloudy"}}
  end)

  assert {:ok, %{temp: 15}} = Weather.get_forecast("London")
end

Property-Based Testing with StreamData

Test properties that hold for all inputs, not just specific examples:

use ExUnitProperties

# ✅ Good: Test a property that always holds
property "User.full_name/1 always returns a string" do
  check all first <- string(:alphanumeric, min_length: 1),
            last <- string(:alphanumeric, min_length: 1) do
    user = %User{first_name: first, last_name: last}
    result = User.full_name(user)
    assert is_binary(result)
    assert String.contains?(result, first)
    assert String.contains?(result, last)
  end
end

# ✅ Good: Roundtrip property
property "encoding then decoding returns the original" do
  check all data <- map_of(string(:alphanumeric), integer()) do
    assert data == data |> MyApp.Encoder.encode() |> MyApp.Encoder.decode()
  end
end

# ✅ Good: Invariant property
property "sorting is idempotent" do
  check all list <- list_of(integer()) do
    sorted = Enum.sort(list)
    assert sorted == Enum.sort(sorted)
  end
end

# ✅ Good: Custom generators for domain types
property "valid emails are accepted, invalid rejected" do
  valid_email = gen all name <- string(:alphanumeric, min_length: 1),
                        domain <- string(:alphanumeric, min_length: 1) do
    "#{name}@#{domain}.com"
  end

  check all email <- valid_email do
    assert {:ok, _} = Accounts.validate_email(email)
  end
end

Running Tests

# Run all tests
mix test

# Run specific file
mix test test/my_app/tasks_test.exs

# Run specific test by line number
mix test test/my_app/tasks_test.exs:42

# Run with coverage
mix test --cover

# Run failed tests only
mix test --failed

# Run tests matching a pattern
mix test --only integration

平台分布

Codex

37.33%
按下载量换算55

Claude

31.18%
按下载量换算46

Cursor

17.71%
按下载量换算26

Gemini CLI

9.64%
按下载量换算14

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills