先看三个变异版各坏在哪

👁️ 2 人浏览 💬 0 人评论 ❤️ 添加收藏

(每道题开头都有同一段:上面那套被测系统、unittest 和 mock,以及 eng_07 的静音 run(*cases)——交回「跑了几条/挂了几条/出错几条」。)

(这一节多了 mutants():三个改坏的 handle——接缝反了、打折阈值写成 >100、末行少了「外币」。好的测试套件要在正确的 handle 上全绿、在每个改坏的上至少红一条。)

把 SAMPLE 分别喂给正确的 handle 和三个变异版,看末行和第一行:

import io, unittest
from unittest import mock

def parse(line):
    w = line.split()
    if len(w) != 3:
        raise ValueError("格式不对:" + line)
    return w[0], int(w[1]), float(w[2])


def subtotal(qty, price):
    return qty * price


def discount(amount):
    return amount * 0.9 if amount >= 100 else amount


class Store:
    def __init__(self):
        self.items = []

    def add(self, name, qty, price):
        self.items.append((name, qty, price))

    def total(self):
        return discount(sum(subtotal(q, p) for _, q, p in self.items))


def fmt(x):
    return ("%.2f" % x).rstrip("0").rstrip(".")


def report(store, rate):
    lines = [n + " " + str(q) + " " + fmt(subtotal(q, p)) for n, q, p in store.items]
    t = store.total()
    lines.append("合计 " + fmt(t) + " 约 " + fmt(t / rate) + " 外币")
    return "\n".join(lines)


def fetch_rate():
    raise ConnectionError("没有网络:汇率服务连不上")


def handle(lines, get_rate=fetch_rate):
    store = Store()
    for line in lines:
        n, q, p = parse(line)
        store.add(n, q, p)
    return report(store, get_rate())


def run(*cases):
    suite = unittest.TestSuite()
    for c in cases:
        suite.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(c))
    r = unittest.TextTestRunner(stream=io.StringIO()).run(suite)
    return str(r.testsRun) + "/" + str(len(r.failures)) + "/" + str(len(r.errors))

SAMPLE = ["苹果 3 2.5", "西瓜 2 30", "米 10 4.2"]
def mutants():
    """三个改坏的版本:接缝反了 / 阈值错了 / 末行格式错了。每个交回 (名字, 改过的 handle)。"""
    def h_seam(lines, get_rate=fetch_rate):
        store = Store()
        for line in lines:
            n, q, p = parse(line)
            store.add(n, p, q)
        return report(store, get_rate())

    def h_threshold(lines, get_rate=fetch_rate):
        store = Store()
        for line in lines:
            store.add(*parse(line))
        t = sum(subtotal(q, p) for _, q, p in store.items)
        t = t * 0.9 if t > 100 else t
        rate = get_rate()
        return "\n".join([n + " " + str(q) + " " + fmt(subtotal(q, p)) for n, q, p in store.items] + ["合计 " + fmt(t) + " 约 " + fmt(t / rate) + " 外币"])

    def h_format(lines, get_rate=fetch_rate):
        store = Store()
        for line in lines:
            store.add(*parse(line))
        t = store.total()
        rate = get_rate()
        return "\n".join([n + " " + str(q) + " " + fmt(subtotal(q, p)) for n, q, p in store.items] + ["合计 " + fmt(t) + " 约 " + fmt(t / rate)])
    return [("seam", h_seam), ("threshold", h_threshold), ("format", h_format)]

rows = []
for name, h in [("ok", handle)] + mutants():
    lines = h(SAMPLE, lambda: 7.0).split("\n")
    rows.append(name + ":" + lines[0].split()[1] + ":" + lines[-1].split()[1] + ":" + str(len(lines[-1].split())))
print("|".join(rows))
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论