Sherlock单元测试编写指南:从基础断言到复杂场景模拟

Sherlock单元测试编写指南:从基础断言到复杂场景模拟

【免费下载链接】sherlock 🔎 Hunt down social media accounts by username across social networks 【免费下载链接】sherlock 项目地址: https://gitcode.com/GitHub_Trending/sh/sherlock

单元测试框架概览

Sherlock项目采用pytest作为单元测试框架,测试代码集中在tests/目录下。该目录包含多个测试模块,覆盖从基础功能验证到复杂场景模拟的完整测试体系:

基础测试用例编写

简单断言测试

最基础的测试形式是直接验证函数返回值,如test_version.py中的版本号验证:

def test_versioning() -> None:
    """Test version string handling."""
    # 此处省略实际实现
    assert True, "版本号验证通过"

参数化测试

使用@pytest.mark.parametrize装饰器可以批量测试不同输入组合,如test_probes.py中的多场景验证:

@pytest.mark.parametrize('site,username',[
    ('GitHub', 'ppfeister'),
    ('GitHub', 'sherlock-project'),
    ('容器平台', 'ppfeister'),
])
def test_known_positives_via_status_code(self, sites_info, site, username):
    assert simple_query(sites_info=sites_info, site=site, username=username) is QueryStatus.CLAIMED

复杂场景模拟技术

随机数据生成

对于边界测试,可生成随机数据验证系统容错能力。以下是test_probes.py中生成超长用户名的实现:

def test_likely_negatives_via_status_code(self, sites_info, site, random_len):
    num_attempts: int = 3
    attempted_usernames: list[str] = []
    status: QueryStatus = QueryStatus.CLAIMED
    for i in range(num_attempts):
        acceptable_types = string.ascii_letters + string.digits
        random_handle = ''.join(random.choice(acceptable_types) for _ in range(random_len))
        attempted_usernames.append(random_handle)
        status = simple_query(sites_info=sites_info, site=site, username=random_handle)
        if status is QueryStatus.AVAILABLE:
            break
    assert status is QueryStatus.AVAILABLE, f"尝试 {num_attempts} 次后仍无法验证可用用户名"

正则表达式验证

站点用户名格式验证通过正则表达式实现,test_probes.py中的非法字符测试示例:

def test_username_illegal_regex(sites_info):
    site: str = 'BitBucket'
    invalid_handle: str = '*#$Y&*JRE'
    pattern = re.compile(sites_info[site]['regexCheck'])
    # 先验证正则表达式本身能捕获非法用户名
    assert pattern.match(invalid_handle) is None
    # 再验证系统正确返回非法状态
    assert simple_query(sites_info=sites_info, site=site, username=invalid_handle) is QueryStatus.ILLEGAL

测试环境配置

夹具(Fixture)设计

conftest.py提供了测试环境的核心配置,包括:

@pytest.fixture
def sites_info():
    """提供站点信息字典的夹具"""
    return fetch_local_manifest()

@pytest.fixture
def sites_obj():
    """提供站点对象的夹具"""
    from sherlock_project.sites import Sites
    return Sites(data=fetch_local_manifest())

测试标记

使用自定义标记对测试进行分类,如test_probes.py中的在线测试标记:

@pytest.mark.online
class TestLiveTargets:
    """对真实目标执行活动探针测试"""
    # 测试方法实现...

测试执行与结果分析

运行测试套件

通过项目根目录的tox.ini配置测试环境,执行:

tox

测试覆盖率

结合pytest-cov插件生成覆盖率报告,配置在pytest.ini中:

[pytest]
addopts = --cov=sherlock_project --cov-report=term-missing
testpaths = tests

高级测试模式

模拟网络请求

对于API交互测试,可使用responses库模拟HTTP响应,示例架构:

def test_api_rate_limit():
    with responses.RequestsMock() as rsps:
        rsps.add(responses.GET, 'https://api.example.com/user',
                 status=429, json={'error': 'rate limited'})
        # 测试代码实现...

行为驱动测试

通过test_ux.py实现用户行为模拟:

def test_wildcard_username_expansion():
    """测试通配符用户名扩展功能"""
    # 此处省略实际实现
    assert True, "通配符扩展测试通过"

测试最佳实践

测试组织原则

  1. 单一职责:每个测试函数只验证一个行为
  2. 可重复性:测试应在任何环境下产生相同结果
  3. 边界覆盖:如test_probes.py中的超长用户名测试
  4. 文档化测试:测试用例应自文档化,清晰表达验证意图

常见问题解决

  • 测试速度慢:使用pytest-xdist实现并行测试
  • 外部依赖:通过模拟隔离外部服务,如test_manifest.py中的本地模式
  • 脆弱测试:避免过度指定断言,关注行为而非实现细节

总结

Sherlock的测试架构展示了从简单断言到复杂场景模拟的完整测试策略。通过合理组织测试代码(tests/)、使用参数化测试、设计灵活夹具,确保了项目在迭代过程中的代码质量。开发人员可参考test_probes.py中的模式扩展新的测试场景,或通过test_ux.py添加新的用户交互测试。

项目架构

完整测试策略文档可参考docs/CODE_OF_CONDUCT.md中的开发规范章节。

【免费下载链接】sherlock 🔎 Hunt down social media accounts by username across social networks 【免费下载链接】sherlock 项目地址: https://gitcode.com/GitHub_Trending/sh/sherlock

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值