[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M76VRPR2D534HBQKZCE8WM93":3,"skill-same:01M76VRPR2D534HBQKZCE8WM93":74},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":28,"commitSha":29,"skillDirectory":30,"forksCount":31,"repositoryHtmlUrl":32,"repositoryHomepageUrl":6,"ownerHtmlUrl":33,"ownerBlogUrl":6,"ownerDescription":34,"updatedAt":35,"install":36,"resources":49},"01M76VRPR2D534HBQKZCE8WM93","pytest",null,"Pytest testing patterns for Python. Trigger: When writing Python tests - fixtures, mocking, markers.","davidcoachdev\u002Fdcfiles","davidcoachdev","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F69812733?v=4","01M758C4BR16TAV1N47W319E9V","David H. Caycedo Blum.","01M758C4CCZA2ZYGA0BGMXCDRH",1,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fpytest\u002FSKILL.md",[],[],"2026-11-12 13:55:43",false,"---\nname: pytest\ndescription: >\n  Pytest testing patterns for Python.\n  Trigger: When writing Python tests - fixtures, mocking, markers.\nlicense: Apache-2.0\nmetadata:\n  author: gentleman-programming\n  version: \"1.0\"\n---\n\n## Basic Test Structure\n\n```python\nimport pytest\n\nclass TestUserService:\n    def test_create_user_success(self):\n        user = create_user(name=\"John\", email=\"john@test.com\")\n        assert user.name == \"John\"\n        assert user.email == \"john@test.com\"\n\n    def test_create_user_invalid_email_fails(self):\n        with pytest.raises(ValueError, match=\"Invalid email\"):\n            create_user(name=\"John\", email=\"invalid\")\n```\n\n## Fixtures\n\n```python\nimport pytest\n\n@pytest.fixture\ndef user():\n    \"\"\"Create a test user.\"\"\"\n    return User(name=\"Test User\", email=\"test@example.com\")\n\n@pytest.fixture\ndef authenticated_client(client, user):\n    \"\"\"Client with authenticated user.\"\"\"\n    client.force_login(user)\n    return client\n\n# Fixture with teardown\n@pytest.fixture\ndef temp_file():\n    path = Path(\"\u002Ftmp\u002Ftest_file.txt\")\n    path.write_text(\"test content\")\n    yield path  # Test runs here\n    path.unlink()  # Cleanup after test\n\n# Fixture scopes\n@pytest.fixture(scope=\"module\")  # Once per module\n@pytest.fixture(scope=\"class\")   # Once per class\n@pytest.fixture(scope=\"session\") # Once per test session\n```\n\n## conftest.py\n\n```python\n# tests\u002Fconftest.py - Shared fixtures\nimport pytest\n\n@pytest.fixture\ndef db_session():\n    session = create_session()\n    yield session\n    session.rollback()\n\n@pytest.fixture\ndef api_client():\n    return TestClient(app)\n```\n\n## Mocking\n\n```python\nfrom unittest.mock import patch, MagicMock\n\nclass TestPaymentService:\n    def test_process_payment_success(self):\n        with patch(\"services.payment.stripe_client\") as mock_stripe:\n            mock_stripe.charge.return_value = {\"id\": \"ch_123\", \"status\": \"succeeded\"}\n\n            result = process_payment(amount=100)\n\n            assert result[\"status\"] == \"succeeded\"\n            mock_stripe.charge.assert_called_once_with(amount=100)\n\n    def test_process_payment_failure(self):\n        with patch(\"services.payment.stripe_client\") as mock_stripe:\n            mock_stripe.charge.side_effect = PaymentError(\"Card declined\")\n\n            with pytest.raises(PaymentError):\n                process_payment(amount=100)\n\n# MagicMock for complex objects\ndef test_with_mock_object():\n    mock_user = MagicMock()\n    mock_user.id = \"user-123\"\n    mock_user.name = \"Test User\"\n    mock_user.is_active = True\n\n    result = get_user_info(mock_user)\n    assert result[\"name\"] == \"Test User\"\n```\n\n## Parametrize\n\n```python\n@pytest.mark.parametrize(\"input,expected\", [\n    (\"hello\", \"HELLO\"),\n    (\"world\", \"WORLD\"),\n    (\"pytest\", \"PYTEST\"),\n])\ndef test_uppercase(input, expected):\n    assert input.upper() == expected\n\n@pytest.mark.parametrize(\"email,is_valid\", [\n    (\"user@example.com\", True),\n    (\"invalid-email\", False),\n    (\"\", False),\n    (\"user@.com\", False),\n])\ndef test_email_validation(email, is_valid):\n    assert validate_email(email) == is_valid\n```\n\n## Markers\n\n```python\n# pytest.ini or pyproject.toml\n[tool.pytest.ini_options]\nmarkers = [\n    \"slow: marks tests as slow\",\n    \"integration: marks integration tests\",\n]\n\n# Usage\n@pytest.mark.slow\ndef test_large_data_processing():\n    ...\n\n@pytest.mark.integration\ndef test_database_connection():\n    ...\n\n@pytest.mark.skip(reason=\"Not implemented yet\")\ndef test_future_feature():\n    ...\n\n@pytest.mark.skipif(sys.platform == \"win32\", reason=\"Unix only\")\ndef test_unix_specific():\n    ...\n\n# Run specific markers\n# pytest -m \"not slow\"\n# pytest -m \"integration\"\n```\n\n## Async Tests\n\n```python\nimport pytest\n\n@pytest.mark.asyncio\nasync def test_async_function():\n    result = await async_fetch_data()\n    assert result is not None\n```\n\n## Commands\n\n```bash\npytest                          # Run all tests\npytest -v                       # Verbose output\npytest -x                       # Stop on first failure\npytest -k \"test_user\"           # Filter by name\npytest -m \"not slow\"            # Filter by marker\npytest --cov=src                # With coverage\npytest -n auto                  # Parallel (pytest-xdist)\npytest --tb=short               # Short traceback\n```\n\n","## Basic Test Structure\n\n```python\nimport pytest\n\nclass TestUserService:\n    def test_create_user_success(self):\n        user = create_user(name=\"John\", email=\"john@test.com\")\n        assert user.name == \"John\"\n        assert user.email == \"john@test.com\"\n\n    def test_create_user_invalid_email_fails(self):\n        with pytest.raises(ValueError, match=\"Invalid email\"):\n            create_user(name=\"John\", email=\"invalid\")\n```\n\n## Fixtures\n\n```python\nimport pytest\n\n@pytest.fixture\ndef user():\n    \"\"\"Create a test user.\"\"\"\n    return User(name=\"Test User\", email=\"test@example.com\")\n\n@pytest.fixture\ndef authenticated_client(client, user):\n    \"\"\"Client with authenticated user.\"\"\"\n    client.force_login(user)\n    return client\n\n# Fixture with teardown\n@pytest.fixture\ndef temp_file():\n    path = Path(\"\u002Ftmp\u002Ftest_file.txt\")\n    path.write_text(\"test content\")\n    yield path  # Test runs here\n    path.unlink()  # Cleanup after test\n\n# Fixture scopes\n@pytest.fixture(scope=\"module\")  # Once per module\n@pytest.fixture(scope=\"class\")   # Once per class\n@pytest.fixture(scope=\"session\") # Once per test session\n```\n\n## conftest.py\n\n```python\n# tests\u002Fconftest.py - Shared fixtures\nimport pytest\n\n@pytest.fixture\ndef db_session():\n    session = create_session()\n    yield session\n    session.rollback()\n\n@pytest.fixture\ndef api_client():\n    return TestClient(app)\n```\n\n## Mocking\n\n```python\nfrom unittest.mock import patch, MagicMock\n\nclass TestPaymentService:\n    def test_process_payment_success(self):\n        with patch(\"services.payment.stripe_client\") as mock_stripe:\n            mock_stripe.charge.return_value = {\"id\": \"ch_123\", \"status\": \"succeeded\"}\n\n            result = process_payment(amount=100)\n\n            assert result[\"status\"] == \"succeeded\"\n            mock_stripe.charge.assert_called_once_with(amount=100)\n\n    def test_process_payment_failure(self):\n        with patch(\"services.payment.stripe_client\") as mock_stripe:\n            mock_stripe.charge.side_effect = PaymentError(\"Card declined\")\n\n            with pytest.raises(PaymentError):\n                process_payment(amount=100)\n\n# MagicMock for complex objects\ndef test_with_mock_object():\n    mock_user = MagicMock()\n    mock_user.id = \"user-123\"\n    mock_user.name = \"Test User\"\n    mock_user.is_active = True\n\n    result = get_user_info(mock_user)\n    assert result[\"name\"] == \"Test User\"\n```\n\n## Parametrize\n\n```python\n@pytest.mark.parametrize(\"input,expected\", [\n    (\"hello\", \"HELLO\"),\n    (\"world\", \"WORLD\"),\n    (\"pytest\", \"PYTEST\"),\n])\ndef test_uppercase(input, expected):\n    assert input.upper() == expected\n\n@pytest.mark.parametrize(\"email,is_valid\", [\n    (\"user@example.com\", True),\n    (\"invalid-email\", False),\n    (\"\", False),\n    (\"user@.com\", False),\n])\ndef test_email_validation(email, is_valid):\n    assert validate_email(email) == is_valid\n```\n\n## Markers\n\n```python\n# pytest.ini or pyproject.toml\n[tool.pytest.ini_options]\nmarkers = [\n    \"slow: marks tests as slow\",\n    \"integration: marks integration tests\",\n]\n\n# Usage\n@pytest.mark.slow\ndef test_large_data_processing():\n    ...\n\n@pytest.mark.integration\ndef test_database_connection():\n    ...\n\n@pytest.mark.skip(reason=\"Not implemented yet\")\ndef test_future_feature():\n    ...\n\n@pytest.mark.skipif(sys.platform == \"win32\", reason=\"Unix only\")\ndef test_unix_specific():\n    ...\n\n# Run specific markers\n# pytest -m \"not slow\"\n# pytest -m \"integration\"\n```\n\n## Async Tests\n\n```python\nimport pytest\n\n@pytest.mark.asyncio\nasync def test_async_function():\n    result = await async_fetch_data()\n    assert result is not None\n```\n\n## Commands\n\n```bash\npytest                          # Run all tests\npytest -v                       # Verbose output\npytest -x                       # Stop on first failure\npytest -k \"test_user\"           # Filter by name\npytest -m \"not slow\"            # Filter by marker\npytest --cov=src                # With coverage\npytest -n auto                  # Parallel (pytest-xdist)\npytest --tb=short               # Short traceback\n```\n\n",{"name":5,"license":15,"metadata":24,"description":27},{"author":25,"version":26},"gentleman-programming","1.0","Pytest testing patterns for Python. Trigger: When writing Python tests - fixtures, mocking, markers.\n","main","5dc86f90a5cbe45db3acd917825461b3ed6937fb","config\u002F.config\u002Fopencode\u002Fskills\u002Fpytest",0,"https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev","🌐 Apasionado por crear soluciones web escalables y eficientes. \r\n🧑‍🏫 Coach Dev.\r\n💻 Frontend Dev. \r\n🎚️Backend Dev.\r\n📊 Agile\u002FScrum.\r\n🚀100% remoto.","2026-08-26 07:28:05",{"source":8,"skillName":5,"commands":37,"prompt":47,"zipAvailable":48},[38,41,44],{"tool":39,"command":40},"npx","npx skills add davidcoachdev\u002Fdcfiles --skill pytest",{"tool":42,"command":43},"bunx","bunx skills add davidcoachdev\u002Fdcfiles --skill pytest",{"tool":45,"command":46},"pnpm","pnpm dlx skills add davidcoachdev\u002Fdcfiles --skill pytest","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fpytest\u002FSKILL.md",true,[50,56,62,66,70],{"path":51,"resourceType":52,"resourceTypeDesc":53,"sizeBytes":54,"sourceHtmlUrl":55},".skill-meta.json","REFERENCE","参考文档",405,"https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fpytest\u002F.skill-meta.json",{"path":57,"resourceType":58,"resourceTypeDesc":59,"sizeBytes":60,"sourceHtmlUrl":61},"assets\u002F01-example.ts","SCRIPT","脚本",22,"https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fpytest\u002Fassets\u002F01-example.ts",{"path":63,"resourceType":52,"resourceTypeDesc":53,"sizeBytes":64,"sourceHtmlUrl":65},"README.md",431,"https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fpytest\u002FREADME.md",{"path":67,"resourceType":52,"resourceTypeDesc":53,"sizeBytes":68,"sourceHtmlUrl":69},"references\u002F01-setup.md",26,"https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fpytest\u002Freferences\u002F01-setup.md",{"path":71,"resourceType":52,"resourceTypeDesc":53,"sizeBytes":72,"sourceHtmlUrl":73},"references\u002F02-patterns.md",28,"https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fpytest\u002Freferences\u002F02-patterns.md",[75,82,89,96,104,111],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":19},"01M7740FETMZY1VTYAEFY1TWY7","zustand-5","Zustand 5 state management patterns. Trigger: When managing React state with Zustand.","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fzustand-5\u002FSKILL.md",[],[],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":19},"01M773ZZM9V68SA1AKP4WF4J29","zod-4","Zod 4 schema validation patterns. Trigger: When using Zod for validation - breaking changes from v3.","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fzod-4\u002FSKILL.md",[],[],{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":95,"publishedAt":19},"01M773ZJFR90CQAY0N9QR40QVP","x-bookmark-quote-posts","Workflow para revisar bookmarks de X\u002FTwitter y convertirlos en drafts de quote posts. Accede a la sección de bookmarks vía browser headless, extrae posts recientes, y genera drafts con voz personal del usuario. No publica ni muta X — solo genera contenido para revisión. Trigger: X bookmarks, Twitter bookmarks, quote posts, bookmark automation, crear quote posts, revisar bookmarks, growth content X.","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fx-bookmark-quote-posts\u002FSKILL.md",[],[],{"skillNo":97,"name":98,"nameZh":6,"description":99,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":100,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":19},"01M773Z2RGV3786FV310SDB0YD","writing-skills","Use when creating new skills, editing existing skills, or verifying skills work before deployment","MIT","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fwriting-skills\u002FSKILL.md",[],[],{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":100,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":110,"publishedAt":19},"01M773YJH3KDSW467CSS63CSRJ","writing-plans","Use when you have a spec or requirements for a multi-step task, before touching code","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fwriting-plans\u002FSKILL.md",[],[],{"skillNo":112,"name":113,"nameZh":6,"description":114,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":117,"publishedAt":19},"01M773Y3S3H2CPRK5S8YFHWB5C","work-unit-commits","Plan commits as reviewable work units. Trigger: implementation, commit splitting, chained PRs, or keeping tests and docs with code.","https:\u002F\u002Fgithub.com\u002Fdavidcoachdev\u002Fdcfiles\u002Fblob\u002Fmain\u002Fconfig\u002F.config\u002Fopencode\u002Fskills\u002Fwork-unit-commits\u002FSKILL.md",[],[]]