String mutations: the two case flips are equivalent wherever the consumer is case-insensitive, and no option turns them off
维护者通常 2 天内回复
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 55/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- python, sqlite
- 领域
- cli, testing-qa, tooling
调研方向
从 operator_string 入口点以及现有的 --disable-mutation-types 和 do_not_mutate_patterns 配置行为开始。使用 example.py、test_example.py 和 pyproject.toml 重现残留的小写和大写变异体,然后添加回归覆盖,证明可以禁用大小写转换而不移除 XX 变异体或索引变异体。
由索引模型根据 Issue 内容生成。
描述
Disclaimer: AI-drafted, verified by me before filing. I answer follow-ups.
operator_string emits three mutants for every string literal: the literal wrapped in XX, lowercased, and uppercased. Where the literal's consumer is case-insensitive -- SQL, codec names, HTTP header names -- the case flips are equivalent mutants by construction.
Expected: a mutation I cannot kill can be switched off, as --disable-mutation-types did in 2.x (#175, added by #225).
Actual: both case flips survive every run, and the only lever in 3.x, do_not_mutate_patterns, matches whole lines, so it drops the XX mutant on that line too.
They were 25% and 11% of all survivors on two of my codebases: re-read on every run, and nothing to be done about them.
Reproduce -- three files, mutmut 3.7.0, pytest 9.1.1, CPython 3.12.12
# example.py
import sqlite3
def note_count(db_path: str) -> int:
con = sqlite3.connect(db_path)
return con.execute("SELECT COUNT(*) FROM notes").fetchone()[0]
# test_example.py
import sqlite3
from example import note_count
def test_note_count(tmp_path):
db = tmp_path / "n.db"
con = sqlite3.connect(db)
con.execute("CREATE TABLE notes (id int)")
con.execute("INSERT INTO notes VALUES (1)")
con.commit()
con.close()
assert note_count(str(db)) == 1
# pyproject.toml
[project]
name = "repro"
version = "0"
requires-python = ">=3.11"
[tool.mutmut]
source_paths = ["example.py"]
$ mutmut run
7/7 🎉 5 🫥 0 ⏰ 0 🤔 0 🙁 2 🔇 0 🧙 0
$ mutmut results
example.x_note_count__mutmut_5: survived
example.x_note_count__mutmut_6: survived
$ mutmut show example.x_note_count__mutmut_5
# example.x_note_count__mutmut_5: survived
--- example.py
+++ example.py
@@ -1,3 +1,3 @@
def note_count(db_path: str) -> int:
con = sqlite3.connect(db_path)
- return con.execute("SELECT COUNT(*) FROM notes").fetchone()[0]
+ return con.execute("select count(*) from notes").fetchone()[0]
$ mutmut show example.x_note_count__mutmut_6 # the same line, uppercased
+ return con.execute("SELECT COUNT(*) FROM NOTES").fetchone()[0]
SQLite parses either casing and resolves table names case-insensitively, so both mutants are equivalent to the original. The only test that would kill them asserts the query string's exact casing, which tests the literal rather than the behaviour.
What the line pattern costs -- 7 mutants become 2
[tool.mutmut]
source_paths = ["example.py"]
do_not_mutate_patterns = ["SELECT"]
$ mutmut run
2/2 🎉 2 🫥 0 ⏰ 0 🤔 0 🙁 0 🔇 0 🧙 0
Five of the seven mutants are gone. Two of them, mutant 4 ("XXSELECT COUNT(*) FROM notesXX") and mutant 7 (.fetchone()[1]), are killed by the test as it stands, so the pattern removes working signal in order to remove two mutants that carry none.
- 主要语言
- Python
- 星标
- 1.5k
- 派生
- 185
- 平均合并
- 1 天 14 小时
- 30 天内合并 PR
- 5
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
boxed/mutmut 的其他 Issue
-
Removing `not` from a parenthesized multi-line expression drops the parentheses (InvalidGeneratedSyntaxException, 3.8.0)可能已有人在做 @jihtsan 于 8 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 2 天内回复
-
`run` with a `name__mutmut_*` pattern runs the whole test suite in the clean-test check可能已有人在做 @Ishaan400 于 19 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 2 天内回复
-
Invalid unary plus generated in match statement可能已有人在做 @GhostCoder6969 于 28 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 68/100
维护者通常 2 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
维护者通常 2 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
维护者通常 2 天内回复
相似的 Issue
-
难度 1/5 1 小时以内 新手友好度 72/100
MIT-LCP/wfdb-python#590 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 77/100
pollen-robotics/reachy_mini#1517 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 69/100
NRLMMD-GEOIPS/pluginify#41 ·
-
难度 2/5 1-3 小时 新手友好度 67/100
scverse/spatialdata#1293 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
UKGovernmentBEIS/inspect_evals#2788 ·
维护者通常 1 天内回复