热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
一键生成全面单元测试,覆盖所有场景,代码更健壮,测试更高效!
from decimal import Decimal import pytest
from target_module import calculate_order_total # 修改为你的模块名
def test_typical_order_percent_discount_with_cap_and_tax_returns_decimal_and_correct_total(): items = [ {'price': '30', 'qty': 2}, # subtotal = 60 ] discount = {'type': 'percent', 'value': '0.10', 'cap': Decimal('5')} # 10% capped at 5 -> discount = 5 tax_rate = Decimal('0.07') # 7%
total = calculate_order_total(items, discount=discount, tax_rate=tax_rate)
# taxed_base = 60 - 5 = 55; tax = 55 * 0.07 = 3.85; total = 58.85 -> Decimal rounded to 2 places
assert isinstance(total, Decimal)
assert total == Decimal('58.85')
def test_empty_cart_returns_zero_decimal_two_places(): total = calculate_order_total([], discount=None, tax_rate=Decimal('0')) assert isinstance(total, Decimal) assert total == Decimal('0.00')
def test_tax_rate_boundary_zero_no_tax(): items = [{'price': '10', 'qty': 2}] # subtotal = 20 total = calculate_order_total(items, tax_rate=Decimal('0')) assert total == Decimal('20.00')
def test_tax_rate_boundary_one_full_tax_on_discounted_base(): items = [{'price': 10, 'qty': 1}] # subtotal = 10 discount = {'type': 'fixed', 'value': 2} # taxed_base = 8 total = calculate_order_total(items, discount=discount, tax_rate=Decimal('1.0')) # total = 8 + 8 = 16 assert total == Decimal('16.00')
def test_fixed_discount_exceeds_subtotal_caps_to_zero_total_even_with_tax(): items = [{'price': '12', 'qty': 1}] # subtotal = 12 discount = {'type': 'fixed', 'value': '100'} # discount capped to subtotal -> taxed_base = 0 total = calculate_order_total(items, discount=discount, tax_rate=Decimal('0.07')) assert total == Decimal('0.00')
def test_negative_price_raises_value_error(): items = [{'price': -1, 'qty': 1}] with pytest.raises(ValueError, match='价格与数量需非负'): calculate_order_total(items)
def test_negative_quantity_raises_value_error(): items = [{'price': '1.00', 'qty': -2}] with pytest.raises(ValueError, match='价格与数量需非负'): calculate_order_total(items)
def test_tax_rate_below_zero_raises_value_error(): items = [{'price': '1', 'qty': 1}] with pytest.raises(ValueError, match='税率需在0到1之间'): calculate_order_total(items, tax_rate=Decimal('-0.01'))
def test_tax_rate_above_one_raises_value_error(): items = [{'price': '1', 'qty': 1}] with pytest.raises(ValueError, match='税率需在0到1之间'): calculate_order_total(items, tax_rate=Decimal('1.0001'))
def test_unknown_discount_type_raises_value_error(): items = [{'price': '10', 'qty': 1}] discount = {'type': 'bogus', 'value': '0.1'} with pytest.raises(ValueError, match='未知折扣类型'): calculate_order_total(items, discount=discount)
def test_prices_and_discount_accept_float_and_string_safely_converted_to_decimal(): items = [ {'price': 19.9, 'qty': 1}, # float price {'price': '10.10', 'qty': 2}, # string price ] discount = {'type': 'percent', 'value': '0.1'} # string percent tax_rate = 0.075 # float tax rate
total = calculate_order_total(items, discount=discount, tax_rate=tax_rate)
# subtotal = 19.9 + 20.2 = 40.1
# discount = 40.1 * 0.1 = 4.01
# taxed_base = 36.09
# tax = 36.09 * 0.075 = 2.70675
# total = 38.79675 -> ROUND_HALF_UP to 38.80
assert total == Decimal('38.80')
def test_discount_cap_negative_raises_value_error(): items = [{'price': '10', 'qty': 1}] discount = {'type': 'percent', 'value': '0.1', 'cap': '-1'} with pytest.raises(ValueError, match='折扣封顶需非负'): calculate_order_total(items, discount=discount)
def test_rounding_half_up_to_two_decimal_places(): items = [{'price': '0.01', 'qty': 1}] # subtotal = 0.01 # tax = 0.01 * 0.5 = 0.005; total = 0.015 -> ROUND_HALF_UP -> 0.02 total = calculate_order_total(items, tax_rate=Decimal('0.5')) assert total == Decimal('0.02')
@pytest.mark.parametrize("bad_item", [ {'qty': 1}, # missing price {'price': '1.00'}, # missing qty ]) def test_item_missing_price_or_qty_raises_value_error(bad_item): with pytest.raises(ValueError, match='item缺少price或qty'): calculate_order_total([bad_item])
@pytest.mark.parametrize("bad_percent", ['-0.1', Decimal('1.1')]) def test_percent_discount_out_of_range_raises_value_error(bad_percent): items = [{'price': '10', 'qty': 1}] discount = {'type': 'percent', 'value': bad_percent} with pytest.raises(ValueError, match='百分比折扣需在0到1之间'): calculate_order_total(items, discount=discount)
def test_fixed_discount_negative_raises_value_error(): items = [{'price': '10', 'qty': 1}] discount = {'type': 'fixed', 'value': '-5'} with pytest.raises(ValueError, match='固定折扣需非负'): calculate_order_total(items, discount=discount)
下面给出使用 JUnit 5 为 RateLimiter 编写的单元测试代码。测试覆盖了正常路径、边界与异常场景,并使用可控时间供应器以精确模拟窗口到期与重置。
文件:testgen/RateLimiterTest.java
package testgen;
import org.junit.jupiter.api.Test; import java.util.function.Supplier;
import static org.junit.jupiter.api.Assertions.*;
public class RateLimiterTest {
// 可控时间供应器
static class MutableClock implements Supplier<Long> {
private long now;
MutableClock(long start) { this.now = start; }
@Override public Long get() { return now; }
void advance(long deltaMillis) { this.now += deltaMillis; }
void set(long newNow) { this.now = newNow; }
}
@Test
void normalPath_capacity3_window1000_allowThree_thenReject_untilBoundary_thenAllow_remainingResetsAndDecrements() {
MutableClock clock = new MutableClock(0L);
RateLimiter rl = new RateLimiter(3, 1000, clock);
assertEquals(3, rl.remaining(), "Initial remaining should equal capacity");
assertTrue(rl.allow(), "1st allow should pass");
assertEquals(2, rl.remaining(), "Remaining should decrement after first allow");
assertTrue(rl.allow(), "2nd allow should pass");
assertEquals(1, rl.remaining(), "Remaining should decrement after second allow");
assertTrue(rl.allow(), "3rd allow should pass");
assertEquals(0, rl.remaining(), "Remaining should be zero after third allow");
assertFalse(rl.allow(), "4th allow should be rejected within same window");
assertEquals(0, rl.remaining(), "Remaining stays zero when capacity exceeded");
// 推进时间到窗口边界(恰等于窗口长度),应当重置
clock.advance(1000L);
long expectedNewWindowStart = clock.get();
assertTrue(rl.allow(), "Allow should pass right at window boundary (reset occurs)");
assertEquals(2, rl.remaining(), "Remaining resets to capacity-1 after boundary allow");
assertEquals(expectedNewWindowStart, rl.getWindowStart(), "Window start should update to current time on reset");
}
@Test
void remainingResetsWhenWindowExpiredBeforeAnyAllow() {
MutableClock clock = new MutableClock(100L);
RateLimiter rl = new RateLimiter(3, 200, clock);
assertEquals(3, rl.remaining(), "Initial remaining");
// 时间恰等于窗口长度触发重置(通过remaining触发)
clock.advance(200L);
long nowAtBoundary = clock.get();
assertEquals(3, rl.remaining(), "Remaining should reset to full capacity at boundary");
assertEquals(nowAtBoundary, rl.getWindowStart(), "Window start should update on reset triggered by remaining()");
}
@Test
void capacityOne_boundaryExactWindowReset() {
MutableClock clock = new MutableClock(0L);
RateLimiter rl = new RateLimiter(1, 100, clock);
assertTrue(rl.allow(), "First allow should pass with capacity 1");
assertFalse(rl.allow(), "Second allow in same window should be rejected");
// 恰到窗口边界后应允许
clock.advance(100L);
assertTrue(rl.allow(), "Allow should pass exactly at window boundary after reset");
assertEquals(0, rl.remaining(), "Remaining should reflect one usage in new window");
}
@Test
void constructorValidation_invalidArguments_throwIllegalArgumentException() {
assertThrows(IllegalArgumentException.class, () -> new RateLimiter(0, 1000));
assertThrows(IllegalArgumentException.class, () -> new RateLimiter(-1, 1000));
assertThrows(IllegalArgumentException.class, () -> new RateLimiter(1, 0));
assertThrows(IllegalArgumentException.class, () -> new RateLimiter(1, -1));
assertThrows(IllegalArgumentException.class, () -> new RateLimiter(1, 1000, null));
}
@Test
void largeCapacity_stateConsistent_andResetsOnExpiry() {
MutableClock clock = new MutableClock(10_000L);
int largeCap = 1_000_000;
RateLimiter rl = new RateLimiter(largeCap, 500, clock);
// 使用少量次数验证剩余与递减
for (int i = 0; i < 10; i++) {
assertTrue(rl.allow(), "Allow should pass while under large capacity");
}
assertEquals(largeCap - 10, rl.remaining(), "Remaining should be capacity minus used");
// 到期后重置
clock.advance(500L);
assertEquals(largeCap, rl.remaining(), "Remaining should reset to full capacity after window expiry");
assertTrue(rl.allow(), "Allow should pass in new window");
assertEquals(largeCap - 1, rl.remaining(), "Remaining should decrement correctly after new window allow");
}
@Test
void windowStartUpdatesOnResetViaAllow() {
MutableClock clock = new MutableClock(1_000L);
RateLimiter rl = new RateLimiter(2, 300, clock);
assertTrue(rl.allow());
assertTrue(rl.allow());
assertFalse(rl.allow(), "Third allow should be rejected in the same window with capacity 2");
long oldStart = rl.getWindowStart();
clock.advance(300L);
long now = clock.get();
assertTrue(rl.allow(), "Allow at exact expiry should succeed and reset window");
assertEquals(now, rl.getWindowStart(), "Window start should update to current time after reset");
assertEquals(1, rl.remaining(), "Remaining should reflect one usage in the new window");
assertTrue(oldStart != rl.getWindowStart(), "Window start must have changed after reset");
}
}
// Adjust the require path to where your module is located const assert = require('assert'); const { parseUserConfig } = require('./parseUserConfig');
describe('parseUserConfig', () => { describe('正常路径场景', () => { it('JSON字符串覆盖重试、超时、端点与特性;未知字段进入extras', () => { const input = JSON.stringify({ retries: 5, timeoutMs: 8000, endpoint: 'http://api.example.com', features: { cache: false, logging: true }, theme: 'dark', extraFlag: true }); const result = parseUserConfig(input);
assert.strictEqual(result.retries, 5);
assert.strictEqual(result.timeoutMs, 8000);
assert.strictEqual(result.endpoint, 'http://api.example.com');
assert.deepStrictEqual(result.features, { cache: false, logging: true });
assert.deepStrictEqual(result.extras, { theme: 'dark', extraFlag: true });
});
it('对象输入并部分覆盖,未提供的特性按默认补齐', () => {
const input = {
retries: 2,
features: { cache: false }, // logging 未提供,按默认 false
custom: { a: 1 }
};
const result = parseUserConfig(input);
assert.strictEqual(result.retries, 2);
assert.strictEqual(result.timeoutMs, 5000);
assert.strictEqual(result.endpoint, 'https://api.example.test');
assert.deepStrictEqual(result.features, { cache: false, logging: false });
assert.deepStrictEqual(result.extras, { custom: { a: 1 } });
// 确保已知键未进入 extras
assert.ok(!('retries' in result.extras));
assert.ok(!('timeoutMs' in result.extras));
assert.ok(!('endpoint' in result.extras));
assert.ok(!('features' in result.extras));
});
it('features值做布尔归一化(类型校验并归一化)', () => {
const input = {
features: { cache: 'yes', logging: 1 }
};
const result = parseUserConfig(input);
assert.deepStrictEqual(result.features, { cache: true, logging: true });
});
});
describe('边界与异常场景', () => { it('缺失所有字段时填默认,extras为空', () => { const result = parseUserConfig({}); assert.strictEqual(result.retries, 3); assert.strictEqual(result.timeoutMs, 5000); assert.strictEqual(result.endpoint, 'https://api.example.test'); assert.deepStrictEqual(result.features, { cache: true, logging: false }); assert.deepStrictEqual(result.extras, {}); });
it('retries在边界0与10时合法', () => {
const r0 = parseUserConfig({ retries: 0 });
assert.strictEqual(r0.retries, 0);
const r10 = parseUserConfig({ retries: 10 });
assert.strictEqual(r10.retries, 10);
});
it('retries越界或非整数抛错', () => {
assert.throws(() => parseUserConfig({ retries: -1 }), /retries must be integer in \[0,10\]/);
assert.throws(() => parseUserConfig({ retries: 11 }), /retries must be integer in \[0,10\]/);
assert.throws(() => parseUserConfig({ retries: 3.5 }), /retries must be integer in \[0,10\]/);
assert.throws(() => parseUserConfig({ retries: '3' }), /retries must be integer in \[0,10\]/);
});
it('timeoutMs非正或非整数抛错', () => {
assert.throws(() => parseUserConfig({ timeoutMs: 0 }), /timeoutMs must be a positive integer/);
assert.throws(() => parseUserConfig({ timeoutMs: -100 }), /timeoutMs must be a positive integer/);
assert.throws(() => parseUserConfig({ timeoutMs: 1000.5 }), /timeoutMs must be a positive integer/);
assert.throws(() => parseUserConfig({ timeoutMs: '5000' }), /timeoutMs must be a positive integer/);
});
it('endpoint未以http://或https://开头或类型错误抛错', () => {
assert.throws(() => parseUserConfig({ endpoint: 'ftp://server' }), /endpoint must start with http:\/\/ or https:\/\//);
assert.throws(() => parseUserConfig({ endpoint: 'api.example.com' }), /endpoint must start with http:\/\/ or https:\/\//);
assert.throws(() => parseUserConfig({ endpoint: 123 }), /endpoint must start with http:\/\/ or https:\/\//);
});
it('非法JSON字符串抛Error', () => {
assert.throws(() => parseUserConfig('{ not json }'), /Invalid JSON/);
assert.throws(() => parseUserConfig('{"a":1,}'), /Invalid JSON/);
});
it('输入类型既不是字符串也不是对象(含null)时抛错', () => {
assert.throws(() => parseUserConfig(42), /Config must be JSON string or object/);
assert.throws(() => parseUserConfig(null), /Config must be JSON string or object/);
});
it('features为空对象时按默认补齐', () => {
const result = parseUserConfig({ features: {} });
assert.deepStrictEqual(result.features, { cache: true, logging: false });
});
it('features不是对象时按默认补齐', () => {
const result = parseUserConfig({ features: 'oops' });
assert.deepStrictEqual(result.features, { cache: true, logging: false });
});
it('extras保留未知键且支持嵌套对象', () => {
const input = {
retries: 2,
timeoutMs: 6000,
endpoint: 'https://example.org',
features: { cache: true },
notes: { a: 1, b: [1, 2] },
theme: 'dark'
};
const result = parseUserConfig(input);
assert.deepStrictEqual(result.extras, { notes: { a: 1, b: [1, 2] }, theme: 'dark' });
});
}); });
针对 根据给定代码与框架编写覆盖完整场景的单元测试 的日常工作场景,该工具旨在解决以下问题:
工具名称: 单元测试编写
功能简介: 根据给定代码与框架编写覆盖完整场景的单元测试,自动生成高质量的测试用例,确保代码逻辑正确性和边界条件覆盖,提升测试效率和代码质量。
构建完整的代码质量保障流程,从代码编写到测试验证再到持续集成。
快速生成复杂代码的高覆盖率单元测试,减少编写测试的时间成本,专注核心开发工作。
通过智能生成的测试用例补全关键场景漏洞,确保代码稳定性和业务可靠性。
借助自动化测试增强团队开发效率,更放心地交付高质量产品上线。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
免费获取高级提示词-优惠即将到期