Token导航 LogoToken导航

Agent Skill · 研究检索

bach-exploratory-testing(巴赫探索性测试)

用于辅助测试设计、自动化测试、用例整理和回归验证。它适合让 Agent 编写单元测试、端到端测试、测试计划或根据失败日志定位问题。使用时需要确认项目测试框架、运行命令和夹具数据,避免为了通过测试而改坏真实逻辑;涉及浏览器或外部服务时,应区分本地模拟、测试环境和生产环境。

bach-exploratory-testing 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 64,698。

总安装 294周安装 12GitHub Stars 6下载 94核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

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

skills.shnpx skills
npx skills add https://github.com/copyleftdev/sk1llz --skill bach-exploratory-testing

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

bach-exploratory-testing 基于 James Bach 的探索性测试理念,提供测试思维与执行风格指南。适用于在 Codex、Claude、Cursor、Gemini CLI 中设计非脚本化、基于知识的测试活动。

强调测试作为 skilled intellectual activity,倡导 context-driven 方法而非机械执行。安装方式:npx skills add https://github.com/copyleftdev/sk1llz --skill bach-exploratory-testing。

使用前需确认权限范围、维护状态,并注意是否会触发联网、命令执行或文件读写操作。

来源仓库内路径:skills/bach-exploratory-testing

上手步骤

4 步
  1. 1

    确认自己的宿主工具

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

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/copyleftdev/sk1llz --skill bach-exploratory-te…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

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

  4. 4

    按最小权限试用

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

常见问题

6 条

bach-exploratory-testing 怎么安装?

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

bach-exploratory-testing 支持哪些 AI 工具?

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

bach-exploratory-testing 需要什么权限?

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

bach-exploratory-testing 是免费的吗?

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

bach-exploratory-testing 用的人多吗?

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

bach-exploratory-testing 安全吗?

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

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

值得选的地方

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

先想清楚的地方

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

适不适合你

更适合

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

不太适合

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

研究检索类 Skill 对比

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

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
bach-exploratory-testing

巴赫探索性测试 · 本页

2946需要联网未明确通过

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

SKILL.md 原文

James Bach Exploratory Testing Style Guide⁠‍⁠​‌​‌​​‌‌‍​‌​​‌​‌‌‍​​‌‌​​​‌‍​‌​​‌‌​​‍​​​​​​​‌‍‌​​‌‌​‌​‍‌​​​​​​​‍‌‌​​‌‌‌‌‍‌‌​​​‌​​‍‌‌‌‌‌‌​‌‍‌‌​‌​​​​‍​‌​‌‌‌‌‌‍​‌​​‌​‌‌‍​‌‌​‌​​‌‍‌​‌​‌‌‌​‍​​‌​‌​​​‍‌‌‌​‌​‌‌‍‌​​​​‌‌​‍​​​‌​​​​‍‌​‌‌​‌‌​‍​​‌‌​‌​‌‍​​​​‌​​‌‍‌‌‌​‌​‌‌⁠‍⁠

Overview

James Bach is a pioneer of exploratory testing and co-founder of the context-driven testing movement. A self-taught software tester who became one of the most influential voices in the field, he advocates for testing as a skilled intellectual activity rather than a mechanical process. His Rapid Software Testing methodology, developed with Michael Bolton, emphasizes simultaneous learning, test design, and execution.

Core Philosophy

"Testing is not a phase. Testing is not a checklist. Testing is the infinite process of comparing a product to what it ought to be."
"Exploratory testing is simultaneous learning, test design, and test execution."
"A good tester is not a person who follows scripts. A good tester is a person who can think."

Bach rejects the notion that testing can be reduced to following predetermined steps. Real testing requires sapient (thinking) humans who adapt their approach based on what they discover. The tester's mind is the primary testing tool.

Design Principles

  1. Context Drives Practice: There is no universal best practice—only practices that fit the context.
  2. Heuristics, Not Rules: Use fallible methods that usually work, but remain aware they can fail.
  3. Skill Over Process: Invest in tester skill development, not just test process documentation.
  4. Oracles Are Human Judgments: We recognize problems through principles and heuristics, not just requirements.
  5. Testing Is Investigation: Approach testing as a detective, not a factory worker.

The Seven Principles of Context-Driven Testing

1. The value of any practice depends on its context.
2. There are good practices in context, but no best practices.
3. People, working together, are the most important part of any project's context.
4. Projects unfold over time in ways that are often not predictable.
5. The product is a solution. If the problem isn't solved, the product doesn't work.
6. Good software testing is a challenging intellectual process.
7. Only through judgment and skill can we do the right things at the right times.

Heuristic Test Strategy Model (HTSM)

Bach's framework for thinking about test strategy:

┌─────────────────────────────────────────────────────────────┐
│                    PROJECT ENVIRONMENT                       │
│  Customers, Information, Developer Relations, Test Team,    │
│  Equipment & Tools, Schedule, Test Items, Deliverables      │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    PRODUCT ELEMENTS                          │
│  Structure, Function, Data, Platform, Operations             │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    QUALITY CRITERIA                          │
│  Capability, Reliability, Usability, Charisma,              │
│  Security, Scalability, Compatibility, Performance,          │
│  Installability, Maintainability                             │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    TEST TECHNIQUES                           │
│  Function, Domain, Stress, Flow, Scenario, Claims,          │
│  User, Risk, Automatic                                       │
└─────────────────────────────────────────────────────────────┘

When Testing

Always

  • Begin with a testing charter or mission
  • Document your mental model of the product
  • Use oracles to identify potential problems
  • Take notes during sessions (not after)
  • Time-box exploratory sessions (60-90 minutes)
  • Debrief after sessions to capture learnings
  • Question requirements—they are often incomplete

Never

  • Follow scripts blindly without thinking
  • Assume requirements are complete or correct
  • Confuse test execution with testing
  • Believe that passing tests means quality
  • Stop exploring when you find one bug
  • Treat automation as a replacement for thinking
  • Assume absence of evidence is evidence of absence

Prefer

  • Questions over assumptions
  • Exploration over confirmation
  • Learning over procedure
  • Skill over certification
  • Models over checklists
  • Collaboration over documentation
  • Oracles over expected results

Code Patterns

Session-Based Test Management

class ExploratorySession:
    """
    A time-boxed exploratory testing session.
    Bach's SBTM: structured freedom for skilled testers.
    """

    def __init__(self,
                 charter: str,
                 duration_minutes: int = 90,
                 tester: str = None):
        self.charter = charter
        self.duration = duration_minutes
        self.tester = tester
        self.start_time = None
        self.end_time = None
        self.notes = []
        self.bugs = []
        self.questions = []
        self.risks = []
        self.areas_explored = []
        self.session_metrics = {}

    def start(self):
        """Begin the session."""
        self.start_time = datetime.now()
        self.log(f"Session started. Charter: {self.charter}")

    def log(self, observation: str, category: str = 'note'):
        """
        Log observations during the session.
        Categories: note, bug, question, risk, idea
        """
        entry = {
            'timestamp': datetime.now(),
            'elapsed': self.elapsed_minutes(),
            'category': category,
            'content': observation
        }

        self.notes.append(entry)

        if category == 'bug':
            self.bugs.append(entry)
        elif category == 'question':
            self.questions.append(entry)
        elif category == 'risk':
            self.risks.append(entry)

    def elapsed_minutes(self) -> float:
        """Time elapsed since session start."""
        if not self.start_time:
            return 0
        return (datetime.now() - self.start_time).total_seconds() / 60

    def remaining_minutes(self) -> float:
        """Time remaining in session."""
        return max(0, self.duration - self.elapsed_minutes())

    def end(self):
        """
        End the session and calculate metrics.
        """
        self.end_time = datetime.now()

        self.session_metrics = {
            'duration_planned': self.duration,
            'duration_actual': self.elapsed_minutes(),
            'bugs_found': len(self.bugs),
            'questions_raised': len(self.questions),
            'risks_identified': len(self.risks),
            'areas_explored': len(self.areas_explored),
            'note_count': len(self.notes)
        }

        self.log("Session ended.")
        return self.generate_report()

    def generate_report(self) -> SessionReport:
        """
        Generate session report for debrief.
        """
        return SessionReport(
            charter=self.charter,
            tester=self.tester,
            duration=self.session_metrics['duration_actual'],
            bugs=self.bugs,
            questions=self.questions,
            risks=self.risks,
            areas=self.areas_explored,
            notes=self.notes,
            metrics=self.session_metrics
        )

class TestCharter:
    """
    A testing charter defines the mission for an exploratory session.

    Format: Explore <target> with <resources> to discover <information>
    """

    def __init__(self,
                 target: str,
                 resources: List[str],
                 information_sought: str,
                 time_box: int = 90,
                 priority: str = 'medium'):
        self.target = target
        self.resources = resources
        self.information = information_sought
        self.time_box = time_box
        self.priority = priority

    def __str__(self) -> str:
        return (f"Explore {self.target} "
                f"with {', '.join(self.resources)} "
                f"to discover {self.information}")

    @classmethod
    def from_risk(cls, risk: Risk, product_area: str) -> 'TestCharter':
        """
        Generate charter from identified risk.
        """
        return cls(
            target=product_area,
            resources=['boundary analysis', 'error guessing', risk.related_technique],
            information_sought=f"whether {risk.description} can occur",
            priority=risk.severity
        )

Oracle Heuristics

class OracleHeuristics:
    """
    Oracles: principles or mechanisms by which we recognize problems.
    Bach's FEW HICCUPPS mnemonic for consistency oracles.
    """

    # FEW HICCUPPS - Consistency Heuristics
    CONSISTENCY_ORACLES = {
        'Familiarity': 'Consistent with what testers have seen before',
        'Explainability': 'Consistent with what can be explained/documented',
        'World': 'Consistent with how the real world works',

        'History': 'Consistent with past versions of the product',
        'Image': 'Consistent with the organization\'s desired image',
        'Comparable_Products': 'Consistent with similar products',
        'Claims': 'Consistent with documentation, ads, specs',
        'User_Expectations': 'Consistent with what users want/expect',
        'Product': 'Consistent with itself (internal consistency)',
        'Purpose': 'Consistent with the explicit/implicit purpose',
        'Statutes': 'Consistent with laws, regulations, standards',
    }

    def __init__(self):
        self.oracle_applications = []

    def apply_oracle(self,
                     observation: str,
                     oracle_type: str,
                     expected_consistency: str,
                     actual_behavior: str) -> OracleResult:
        """
        Apply an oracle to evaluate observed behavior.
        """
        is_consistent = self.evaluate_consistency(
            expected_consistency,
            actual_behavior
        )

        result = OracleResult(
            oracle=oracle_type,
            observation=observation,
            expected=expected_consistency,
            actual=actual_behavior,
            consistent=is_consistent,
            confidence=self.assess_confidence(oracle_type),
            notes=[]
        )

        self.oracle_applications.append(result)
        return result

    def evaluate_consistency(self, expected: str, actual: str) -> bool:
        """
        This requires human judgment—cannot be fully automated.
        Returns a preliminary assessment.
        """
        # This is where human thinking is essential
        # Automation can only flag for review
        return None  # Requires human judgment

    def assess_confidence(self, oracle_type: str) -> str:
        """
        Some oracles are more reliable than others.
        """
        high_confidence = ['Claims', 'Statutes', 'Product']
        medium_confidence = ['User_Expectations', 'Comparable_Products', 'History']
        low_confidence = ['Familiarity', 'World', 'Image']

        if oracle_type in high_confidence:
            return 'HIGH'
        elif oracle_type in medium_confidence:
            return 'MEDIUM'
        else:
            return 'LOW'

    def generate_test_ideas(self, product_element: str) -> List[str]:
        """
        Generate test ideas by applying each oracle.
        """
        ideas = []

        for oracle, description in self.CONSISTENCY_ORACLES.items():
            ideas.append(
                f"Test {product_element} for {oracle} consistency: "
                f"Is it {description.lower()}?"
            )

        return ideas

class ProductCoverageModel:
    """
    Model the product to guide exploration.
    SFDPOT: Structure, Function, Data, Platform, Operations, Time
    """

    ELEMENTS = {
        'Structure': [
            'Code modules',
            'Database schemas',
            'File systems',
            'Configuration files',
            'Dependencies',
            'Interfaces'
        ],
        'Function': [
            'Features',
            'Error handling',
            'Calculations',
            'Transformations',
            'Workflows',
            'Business rules'
        ],
        'Data': [
            'Input data',
            'Output data',
            'Stored data',
            'Data states',
            'Data flows',
            'Data constraints'
        ],
        'Platform': [
            'Operating systems',
            'Browsers',
            'Hardware',
            'Networks',
            'External services',
            'Configurations'
        ],
        'Operations': [
            'User scenarios',
            'Startup/shutdown',
            'Recovery',
            'Maintenance',
            'Updates',
            'Integration'
        ],
        'Time': [
            'Concurrent usage',
            'Timeouts',
            'Date/time handling',
            'Scheduling',
            'Sequences',
            'Race conditions'
        ]
    }

    def __init__(self, product_name: str):
        self.product = product_name
        self.coverage_map = {element: [] for element in self.ELEMENTS}
        self.explored_areas = set()

    def map_product(self, element: str, specifics: List[str]):
        """
        Map specific product elements for coverage tracking.
        """
        if element in self.coverage_map:
            self.coverage_map[element].extend(specifics)

    def mark_explored(self, element: str, specific: str, session_id: str):
        """
        Mark an area as explored.
        """
        self.explored_areas.add((element, specific, session_id))

    def coverage_gaps(self) -> Dict[str, List[str]]:
        """
        Identify areas not yet explored.
        """
        gaps = {}
        explored_specifics = {(e, s) for e, s, _ in self.explored_areas}

        for element, specifics in self.coverage_map.items():
            unexplored = [s for s in specifics if (element, s) not in explored_specifics]
            if unexplored:
                gaps[element] = unexplored

        return gaps

    def suggest_charters(self) -> List[str]:
        """
        Suggest test charters based on coverage gaps.
        """
        charters = []
        gaps = self.coverage_gaps()

        for element, specifics in gaps.items():
            for specific in specifics[:3]:  # Top 3 per element
                charters.append(
                    f"Explore {specific} ({element}) to discover potential problems"
                )

        return charters

Test Heuristics

class TestHeuristics:
    """
    Heuristics are fallible methods for solving problems.
    Bach's testing heuristics for generating test ideas.
    """

    # ZOMBIE heuristic for boundaries
    ZOMBIE = {
        'Zero': 'Test with zero, empty, null, none',
        'One': 'Test with one, single, first, minimum',
        'Many': 'Test with many, multiple, maximum, large',
        'Boundary': 'Test at boundaries, edges, limits',
        'Interface': 'Test at interfaces, handoffs, integrations',
        'Exceptions': 'Test error conditions, invalid inputs, edge cases'
    }

    # CRUSSPIC STMPL for quality criteria
    QUALITY_CRITERIA = {
        'Capability': 'Can it perform its functions?',
        'Reliability': 'Will it work consistently?',
        'Usability': 'Can real users use it?',
        'Security': 'Is it protected from threats?',
        'Scalability': 'Does it handle growth?',
        'Performance': 'Is it fast enough?',
        'Installability': 'Can it be deployed?',
        'Compatibility': 'Does it work with other things?',
        'Supportability': 'Can it be maintained?',
        'Testability': 'Can it be tested effectively?',
        'Maintainability': 'Can it be changed?',
        'Portability': 'Does it work in different environments?',
        'Localizability': 'Can it be adapted for different locales?'
    }

    def generate_boundary_tests(self, variable: str, data_type: str) -> List[str]:
        """
        Generate test ideas using ZOMBIE heuristic.
        """
        tests = []

        if data_type == 'numeric':
            tests.extend([
                f"{variable} = 0 (Zero)",
                f"{variable} = 1 (One)",
                f"{variable} = -1 (Negative one)",
                f"{variable} = MAX_INT (Many/Boundary)",
                f"{variable} = MIN_INT (Many/Boundary)",
                f"{variable} = MAX + 1 (Boundary overflow)",
                f"{variable} = decimal value (Interface)",
                f"{variable} = null/undefined (Exception)",
                f"{variable} = NaN (Exception)",
            ])
        elif data_type == 'string':
            tests.extend([
                f"{variable} = '' (Zero/Empty)",
                f"{variable} = single char (One)",
                f"{variable} = very long string (Many)",
                f"{variable} = max length (Boundary)",
                f"{variable} = max + 1 (Boundary)",
                f"{variable} = special characters (Interface)",
                f"{variable} = unicode (Interface)",
                f"{variable} = null (Exception)",
                f"{variable} = SQL injection (Exception/Security)",
            ])
        elif data_type == 'collection':
            tests.extend([
                f"{variable} = [] empty (Zero)",
                f"{variable} = [1 item] (One)",
                f"{variable} = [many items] (Many)",
                f"{variable} = [max items] (Boundary)",
                f"{variable} = [duplicate items] (Interface)",
                f"{variable} = null (Exception)",
                f"{variable} = nested collections (Interface)",
            ])

        return tests

    def generate_quality_tests(self, feature: str) -> Dict[str, List[str]]:
        """
        Generate test ideas for each quality criterion.
        """
        tests = {}

        for criterion, question in self.QUALITY_CRITERIA.items():
            tests[criterion] = [
                f"{feature}: {question}",
                f"What would make {feature} fail {criterion.lower()}?",
                f"How would a user judge {feature}'s {criterion.lower()}?",
            ]

        return tests

    def soap_opera_testing(self, workflow: str) -> List[str]:
        """
        Soap Opera Testing: dramatic, complex, intertwined scenarios.
        Bach's technique for finding interaction bugs.
        """
        return [
            f"Start {workflow}, interrupt midway, start another",
            f"Run {workflow} with minimum permissions",
            f"Run {workflow} with conflicting concurrent users",
            f"Start {workflow}, lose connection, reconnect",
            f"Run {workflow} with corrupted cache/state",
            f"Complete {workflow}, immediately undo, redo",
            f"Run {workflow} at system resource limits",
            f"Interleave {workflow} with upgrade/migration",
        ]

    def touring_heuristics(self, application: str) -> Dict[str, str]:
        """
        Touring: systematic exploration strategies.
        Different "tours" reveal different problems.
        """
        return {
            'Guidebook Tour': f"Follow the documentation exactly for {application}",
            'Money Tour': f"Test the features that sell {application}",
            'Landmark Tour': f"Navigate between major features of {application}",
            'Intellectual Tour': f"Find the most complex parts of {application}",
            'FedEx Tour': f"Follow data through {application} end to end",
            'Garbage Tour': f"Look for dead code and unused features in {application}",
            'Bad Neighborhood Tour': f"Focus on historically buggy areas of {application}",
            'Museum Tour': f"Test legacy code and old features in {application}",
            'Back Alley Tour': f"Test least-used features of {application}",
            'All-Nighter Tour': f"Test {application} over extended time periods",
        }

Rapid Software Testing Session

class RapidTestingSession:
    """
    Rapid Software Testing: Bach & Bolton's methodology.
    Testing as a performance, not a procedure.
    """

    def __init__(self,
                 product: str,
                 tester: 'SkilledTester',
                 stakeholder_info: Dict):
        self.product = product
        self.tester = tester
        self.stakeholder = stakeholder_info
        self.mental_model = ProductCoverageModel(product)
        self.oracles = OracleHeuristics()
        self.heuristics = TestHeuristics()
        self.sessions = []
        self.findings = []

    def analyze_context(self) -> ContextAnalysis:
        """
        Understand the project context before testing.
        """
        return ContextAnalysis(
            who_is_the_customer=self.stakeholder.get('customer'),
            what_is_the_mission=self.stakeholder.get('mission'),
            what_does_quality_mean=self.stakeholder.get('quality_definition'),
            what_threatens_quality=self.stakeholder.get('risks'),
            what_resources_exist=self.stakeholder.get('resources'),
            what_constraints_exist=self.stakeholder.get('constraints'),
            what_has_been_done=self.stakeholder.get('prior_testing'),
        )

    def create_test_strategy(self, context: ContextAnalysis) -> TestStrategy:
        """
        Build a test strategy based on context.
        No best practices—only practices that fit this context.
        """
        strategy = TestStrategy(product=self.product)

        # Prioritize based on risks
        for risk in context.what_threatens_quality:
            strategy.add_focus_area(
                area=risk.area,
                priority=risk.severity,
                techniques=self.select_techniques(risk),
                time_allocation=self.estimate_time(risk)
            )

        # Generate charters for each focus area
        for area in strategy.focus_areas:
            charters = self.generate_charters(area)
            strategy.add_charters(area.name, charters)

        return strategy

    def select_techniques(self, risk: Risk) -> List[str]:
        """
        Select testing techniques based on risk characteristics.
        """
        techniques = []

        if risk.involves_boundaries:
            techniques.append('Boundary Analysis (ZOMBIE)')
        if risk.involves_user_interaction:
            techniques.append('Scenario Testing')
            techniques.append('Touring')
        if risk.involves_data:
            techniques.append('Data Flow Testing')
            techniques.append('CRUD Testing')
        if risk.involves_integration:
            techniques.append('Interface Testing')
            techniques.append('Soap Opera Testing')
        if risk.involves_time:
            techniques.append('Stress Testing')
            techniques.append('Longevity Testing')

        # Always include exploratory
        techniques.append('Exploratory Testing')

        return techniques

    def run_session(self, charter: TestCharter) -> SessionReport:
        """
        Run a time-boxed exploratory testing session.
        """
        session = ExploratorySession(
            charter=str(charter),
            duration_minutes=charter.time_box,
            tester=self.tester.name
        )

        session.start()

        # The actual testing happens here—human cognition
        # This framework supports but doesn't replace the tester

        self.sessions.append(session)
        return session  # Tester controls when to end

    def debrief(self, session: ExploratorySession) -> DebriefNotes:
        """
        Post-session debrief: capture learnings and adjust strategy.
        """
        report = session.generate_report()

        debrief = DebriefNotes(
            session_id=id(session),
            what_was_tested=session.areas_explored,
            what_was_found=session.bugs,
            what_was_learned=self.extract_learnings(session),
            what_should_change=self.recommend_changes(session),
            new_questions=session.questions,
            new_risks=session.risks,
        )

        # Update mental model based on session
        for area in session.areas_explored:
            self.mental_model.mark_explored(
                area['element'],
                area['specific'],
                str(id(session))
            )

        return debrief

    def extract_learnings(self, session: ExploratorySession) -> List[str]:
        """
        What did we learn about the product?
        """
        learnings = []

        for note in session.notes:
            if 'learned' in note['content'].lower():
                learnings.append(note['content'])
            if 'realized' in note['content'].lower():
                learnings.append(note['content'])
            if 'discovered' in note['content'].lower():
                learnings.append(note['content'])

        return learnings

    def recommend_changes(self, session: ExploratorySession) -> List[str]:
        """
        What should we do differently next?
        """
        recommendations = []

        if session.session_metrics['bugs_found'] > 3:
            recommendations.append(
                "High bug density—consider deeper exploration of this area"
            )

        if session.session_metrics['questions_raised'] > 5:
            recommendations.append(
                "Many questions—schedule stakeholder discussion"
            )

        return recommendations

Mental Model

Bach approaches testing by asking:

  1. What is the mission? Who cares, and what do they need to know?
  2. What could go wrong? Risks drive test focus
  3. How will I recognize a problem? Which oracles apply?
  4. What have I covered? Maintain a mental model of the product
  5. What did I learn? Each test teaches something

The Session Checklist

□ Charter defined (Explore X with Y to discover Z)
□ Time-box set (60-90 minutes typical)
□ Oracles identified (how will I recognize problems?)
□ Note-taking ready (real-time, not after)
□ Product model in mind (SFDPOT coverage)
□ Heuristics available (ZOMBIE, touring, soap opera)
□ Questions captured (for stakeholder follow-up)
□ Debrief scheduled (capture learnings immediately)

Signature Bach Moves

  • Session-Based Test Management (SBTM)
  • Heuristic Test Strategy Model (HTSM)
  • FEW HICCUPPS consistency oracles
  • SFDPOT product coverage model
  • Exploratory testing charters
  • Context-driven approach (no best practices)
  • Soap Opera Testing for complex scenarios
  • Touring heuristics for systematic exploration

平台分布

Codex

33.45%
按下载量换算31

Claude

31.31%
按下载量换算29

Cursor

18.76%
按下载量换算18

Gemini CLI

8.73%
按下载量换算8

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

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

继续浏览同类 Skills