热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
为指定函数生成全面的单元测试,包括边界情况和错误处理,确保测试覆盖完整,支持CI/CD流程中的代码质量保障与持续集成效果提升。
# pytest unit tests for slugify(title: str) -> str
# Replace 'your_module' below with the actual module name where slugify is defined.
import pytest
from your_module import slugify
# 异常处理:类型校验(非字符串应抛出 TypeError)
@pytest.mark.parametrize("bad_input", [None, 123, 3.14, ["a"], {"t": "x"}, b"bytes"])
def test_slugify_type_error_on_non_string(bad_input):
with pytest.raises(TypeError):
slugify(bad_input)
# 文档示例校验(确保示例结果一致)
@pytest.mark.parametrize(
"title, expected",
[
(" Café déjà vu! ", "cafe-deja-vu"),
("版本2.0 发布", "2-0"),
],
)
def test_slugify_doc_examples(title, expected):
assert slugify(title) == expected
# 核心逻辑:去除重音与变音符,转换为 ASCII 并小写
@pytest.mark.parametrize(
"title, expected",
[
("Über Façade Coöperate", "uber-facade-cooperate"), # ü, ç, ö
("mañana", "manana"), # ñ
("Crème brûlée", "creme-brulee"), # è, û, é
("straße", "strae"), # ß 无 ASCII 映射,按实现被忽略
],
)
def test_slugify_diacritics_removed_and_lowercased(title, expected):
assert slugify(title) == expected
# 核心逻辑:非字母数字序列替换为单个连字符,并折叠重复连字符
@pytest.mark.parametrize(
"title, expected",
[
("Hello---World!!!___", "hello-world"),
("a---b--c", "a-b-c"),
("foo_bar__baz", "foo-bar-baz"),
("Don’t stop!!!", "dont-stop"), # 弯引号被移除,其余标点合并为单个连字符
("Don't Stop", "don-t-stop"), # 直引号 -> 连字符
],
)
def test_slugify_non_alnum_replacement_and_hyphen_collapse(title, expected):
assert slugify(title) == expected
# 边界条件:去除首尾连字符与空白
@pytest.mark.parametrize(
"title, expected",
[
(" --Hello-- ", "hello"),
("----Title----", "title"),
(" A ", "a"),
],
)
def test_slugify_strip_edges(title, expected):
assert slugify(title) == expected
# 边界条件:当归一化后不剩字母数字时应返回空字符串
@pytest.mark.parametrize(
"title",
[
"",
"!!!",
"————", # 全为非 ASCII 标点
"版本", # 非 ASCII 且无数字
"😀😅🔥", # emoji
"--__--", # 仅分隔符
],
)
def test_slugify_returns_empty_when_no_alnum_remains(title):
assert slugify(title) == ""
# 数字保留与标点处理
@pytest.mark.parametrize(
"title, expected",
[
("123 Go", "123-go"),
("Release 2.0.1-beta", "release-2-0-1-beta"),
("v1.2.3", "v1-2-3"),
("版本2.0 发布", "2-0"),
],
)
def test_slugify_numbers_preserved_and_punctuation_to_hyphen(title, expected):
assert slugify(title) == expected
# 已是 slug 的字符串应保持(除小写化与规范化外无额外改变)
@pytest.mark.parametrize(
"title, expected",
[
("some-slug", "some-slug"),
("Some-Slug", "some-slug"),
("clean-slug-123", "clean-slug-123"),
],
)
def test_slugify_already_slug_preserved(title, expected):
assert slugify(title) == expected
# 非 ASCII 空白(如不间断空格、全角空格)在 ASCII 归一化环节会被移除而非替换为连字符
@pytest.mark.parametrize(
"title, expected",
[
("A\u00A0B", "ab"), # 不间断空格被丢弃 -> 无连字符
("HELLO 123", "hello123"), # 全角空格被丢弃;全角字母数字归一化
],
)
def test_slugify_non_ascii_whitespace_removed(title, expected):
assert slugify(title) == expected
# 全角/兼容字符数字与字母的归一化
@pytest.mark.parametrize(
"title, expected",
[
("HELLO 123", "hello-123"), # ASCII 空格 -> 连字符;全角数字 -> ASCII 数字
("𝟙𝟚3", "123"), # 数学双线体与全角数字归一化为 ASCII 数字
],
)
def test_slugify_fullwidth_and_compat_digits(title, expected):
assert slugify(title) == expected
# 行分隔与制表符等 ASCII 空白按规则替换为单个连字符
@pytest.mark.parametrize(
"title, expected",
[
("line1\nline2\tline3", "line1-line2-line3"),
("multi \r space", "multi-space"),
],
)
def test_slugify_ascii_whitespace_to_hyphen(title, expected):
assert slugify(title) == expected
package text;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* Unit tests for TextUtils.truncateWithEllipsis using JUnit Jupiter.
* Covers: null handling, invalid maxChars, no-truncation paths, wordBoundary behavior,
* and trimming of trailing whitespace across different whitespace characters and Unicode.
*/
public class TextUtilsTest {
// === Boundary & Exception Handling ===
// Null input should return null, regardless of wordBoundary flag.
@Test
void nullInputReturnsNull() {
assertNull(TextUtils.truncateWithEllipsis(null, 5, false));
assertNull(TextUtils.truncateWithEllipsis(null, 5, true));
}
// maxChars < 1 should throw IllegalArgumentException.
@Test
void maxCharsLessThanOneThrows() {
assertThrows(IllegalArgumentException.class,
() -> TextUtils.truncateWithEllipsis("abc", 0, false));
assertThrows(IllegalArgumentException.class,
() -> TextUtils.truncateWithEllipsis("abc", -1, true));
}
// === No Truncation Paths (text length <= maxChars) ===
// Returns original text unchanged when length <= maxChars.
@Test
void returnsOriginalWhenLengthEqualOrLess() {
assertEquals("Hello", TextUtils.truncateWithEllipsis("Hello", 5, true));
assertEquals("短句", TextUtils.truncateWithEllipsis("短句", 10, true));
// Trailing spaces should be preserved when not truncated.
assertEquals("Hi ", TextUtils.truncateWithEllipsis("Hi ", 10, false));
// Only spaces, not truncated.
assertEquals(" ", TextUtils.truncateWithEllipsis(" ", 5, true));
}
// === Truncation without wordBoundary ===
// Exact cut at maxChars and append ellipsis.
@Test
void truncateWithoutWordBoundaryExactCut() {
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello world", 5, false));
assertEquals("ab...", TextUtils.truncateWithEllipsis("abc", 2, false));
assertEquals("短句...", TextUtils.truncateWithEllipsis("短句测试", 2, false));
}
// Trailing spaces at the cut are removed before ellipsis.
@Test
void truncateWithoutWordBoundaryTrailingSpacesTrimmed() {
// Cut yields trailing space, which should be trimmed.
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello world", 6, false));
// Multiple spaces trimmed.
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello world", 8, false));
// Tab at the cut should be trimmed.
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello\tworld", 6, false));
// Newline at the cut should be trimmed.
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello\nworld", 6, false));
// If the cut is a space-only segment, trimmed to empty then ellipsis.
assertEquals("...", TextUtils.truncateWithEllipsis(" a", 1, false));
assertEquals("...", TextUtils.truncateWithEllipsis(" b", 2, false));
}
// === Truncation with wordBoundary ===
// Cut at last whitespace within limit; whitespace itself is excluded from substring.
@Test
void wordBoundaryCutsAtLastWhitespaceWithinLimit() {
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello world", 7, true));
assertEquals("Hello world...", TextUtils.truncateWithEllipsis("Hello world again", 12, true));
// Multiple spaces: should still cut before the last space within limit and trim remaining trailing spaces.
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello world", 8, true));
}
// Whitespace exactly at index 0 should not be used as a cut point (idx > 0 requirement).
@Test
void wordBoundaryDoesNotCutWhenWhitespaceIndexIsZero() {
assertEquals("...", TextUtils.truncateWithEllipsis(" hello", 1, true)); // cut=1, substring is " ", trimmed to empty
}
// No whitespace within or at the cut window -> fall back to hard cut at maxChars.
@Test
void wordBoundaryFallsBackWhenNoWhitespaceWithinLimit() {
assertEquals("Super...", TextUtils.truncateWithEllipsis("Supercalifragilistic", 5, true));
}
// Whitespace exactly at position == maxChars is ignored by lastWhitespaceBefore (since it scans up to limit-1).
@Test
void wordBoundaryIgnoresWhitespaceExactlyAtLimit() {
// "HelloWorld" (10 chars) then a space at index 10; limit=10, space at limit is ignored.
assertEquals("HelloWorld...", TextUtils.truncateWithEllipsis("HelloWorld test", 10, true));
}
// === Mixed whitespace trimming checks ===
// Space at cut: trimmed
@Test
void trimsSpaceAtCut() {
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello world", 6, true));
}
// Newline and tab at cut: trimmed
@Test
void trimsNewlineAndTabAtCut() {
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello\nworld", 6, true));
assertEquals("Hello...", TextUtils.truncateWithEllipsis("Hello\tworld", 6, true));
}
}
'use strict';
const assert = require('assert');
/**
* Function under test
*/
/**
* Simple template rendering: replaces {{key}} with values from data.
* Features:
* - Supports default values: {{key|default text}}.
* - If options.strict is true, throws if a placeholder has no provided value.
* - Non-string values are coerced with String().
* - tpl must be a string; throws TypeError otherwise.
*/
function renderTemplate(tpl, data, options) {
if (typeof tpl !== 'string') {
throw new TypeError('tpl must be a string');
}
const opts = Object.assign({ strict: false }, options || {});
const ctx = data || {};
return tpl.replace(/{{\s*([a-zA-Z0-9_.-]+)(?:\|([^}]+))?\s*}}/g, (m, key, def) => {
const val = getByPath(ctx, key);
if (val == null) {
if (opts.strict && def == null) {
throw new Error('Missing value for ' + key);
}
return def != null ? String(def) : (opts.strict ? '' : m);
}
return String(val);
});
}
function getByPath(obj, path) {
const parts = path.split('.');
let cur = obj;
for (const p of parts) {
if (cur == null || typeof cur !== 'object' || !(p in cur)) {
return undefined;
}
cur = cur[p];
}
return cur;
}
describe('renderTemplate', () => {
// Type enforcement: tpl must be a string
describe('type checks', () => {
it('throws TypeError when tpl is not a string', () => {
const invalids = [null, undefined, 123, {}, [], () => {}];
for (const v of invalids) {
assert.throws(() => renderTemplate(v, {}), TypeError);
}
});
it('returns tpl unchanged when there are no placeholders', () => {
const s = 'Hello world';
assert.strictEqual(renderTemplate(s, {}), s);
});
});
// Core replacement logic
describe('basic replacement', () => {
it('replaces a single placeholder with provided value', () => {
const out = renderTemplate('Hello {{name}}', { name: 'Ada' });
assert.strictEqual(out, 'Hello Ada');
});
it('replaces multiple occurrences of the same key', () => {
const out = renderTemplate('X {{name}} {{name}} Y', { name: 'Bob' });
assert.strictEqual(out, 'X Bob Bob Y');
});
it('supports whitespace around key inside placeholder', () => {
const out = renderTemplate('Hi {{ user.name }}!', { user: { name: 'Ada' } });
assert.strictEqual(out, 'Hi Ada!');
});
});
// Non-string value coercion
describe('value coercion with String()', () => {
it('coerces numbers', () => {
const out = renderTemplate('Value: {{n}}', { n: 42 });
assert.strictEqual(out, 'Value: 42');
});
it('coerces booleans', () => {
const outTrue = renderTemplate('Flag: {{f}}', { f: true });
const outFalse = renderTemplate('Flag: {{f}}', { f: false });
assert.strictEqual(outTrue, 'Flag: true');
assert.strictEqual(outFalse, 'Flag: false');
});
it('coerces objects', () => {
const out = renderTemplate('Obj: {{o}}', { o: { a: 1 } });
assert.strictEqual(out, 'Obj: [object Object]');
});
it('coerces Date via String()', () => {
const d = new Date('2020-01-01T00:00:00Z');
const out = renderTemplate('Date: {{d}}', { d });
assert.strictEqual(out, `Date: ${String(d)}`);
});
});
// Default values behavior
describe('default values', () => {
it('uses default when key is missing and strict is false (default)', () => {
const out = renderTemplate('Hello {{name|friend}}', {});
assert.strictEqual(out, 'Hello friend');
});
it('uses default when value is null', () => {
const out = renderTemplate('Hello {{name|friend}}', { name: null });
assert.strictEqual(out, 'Hello friend');
});
it('uses default when value is undefined', () => {
const out = renderTemplate('Hello {{name|friend}}', { });
assert.strictEqual(out, 'Hello friend');
});
it('preserves spaces inside default text', () => {
const out = renderTemplate('Hello {{name| friend }}', {});
assert.strictEqual(out, 'Hello friend ');
});
it('supports default text containing the pipe character', () => {
const out = renderTemplate('Hello {{name|foo|bar}}', {});
assert.strictEqual(out, 'Hello foo|bar');
});
it('supports empty default string', () => {
const out = renderTemplate('X{{missing|}}Y', {});
assert.strictEqual(out, 'XY');
});
});
// Strict mode behavior
describe('strict mode', () => {
it('throws when missing value and no default', () => {
assert.throws(
() => renderTemplate('Hello {{name}}', {}, { strict: true }),
(err) => err instanceof Error && /Missing value for name/.test(err.message)
);
});
it('does not throw when default is provided', () => {
const out = renderTemplate('Hello {{name|friend}}', {}, { strict: true });
assert.strictEqual(out, 'Hello friend');
});
it('throws when nested value is missing and no default', () => {
assert.throws(
() => renderTemplate('Hi {{user.name}}', { user: {} }, { strict: true }),
(err) => err instanceof Error && /Missing value for user\.name/.test(err.message)
);
});
});
// Path resolution with getByPath
describe('path resolution and key formats', () => {
it('supports nested paths with dots', () => {
const out = renderTemplate('Hello {{user.name}}', { user: { name: 'Ada' } });
assert.strictEqual(out, 'Hello Ada');
});
it('falls back to default when intermediate path is not an object', () => {
const out = renderTemplate('Hello {{user.name|friend}}', { user: 'string' });
assert.strictEqual(out, 'Hello friend');
});
it('supports keys with hyphens', () => {
const out = renderTemplate('Hi {{user-name}}', { 'user-name': 'Bob' });
assert.strictEqual(out, 'Hi Bob');
});
it('supports keys with underscores and numbers', () => {
const out = renderTemplate('ID: {{user_1}}', { user_1: 7 });
assert.strictEqual(out, 'ID: 7');
});
it('supports array index in path', () => {
const out = renderTemplate('Item: {{items.0.name}}', { items: [{ name: 'A' }, { name: 'B' }] });
assert.strictEqual(out, 'Item: A');
});
it('array path falls back to default when index missing', () => {
const out = renderTemplate('Item: {{items.2.name|X}}', { items: [{ name: 'A' }, { name: 'B' }] });
assert.strictEqual(out, 'Item: X');
});
});
// Missing values behavior when not strict
describe('missing values when not strict', () => {
it('leaves placeholder unchanged when key missing and no default (strict=false)', () => {
const out = renderTemplate('Hi {{who}}', {}, { strict: false });
assert.strictEqual(out, 'Hi {{who}}');
});
it('leaves placeholder unchanged with data as non-object and no default', () => {
const out = renderTemplate('Val: {{toString}}', 42, { strict: false });
assert.strictEqual(out, 'Val: {{toString}}');
});
});
// Handling null/undefined distinctly from false/0
describe('null/undefined vs falsy non-null', () => {
it('treats 0 as a valid value', () => {
const out = renderTemplate('Zero: {{n}}', { n: 0 });
assert.strictEqual(out, 'Zero: 0');
});
it('treats false as a valid value', () => {
const out = renderTemplate('Bool: {{b}}', { b: false });
assert.strictEqual(out, 'Bool: false');
});
it('treats undefined as missing (uses default)', () => {
const out = renderTemplate('Undef: {{x|def}}', { });
assert.strictEqual(out, 'Undef: def');
});
it('treats null as missing (uses default)', () => {
const out = renderTemplate('Null: {{x|def}}', { x: null });
assert.strictEqual(out, 'Null: def');
});
});
// Multiple placeholders with mixed cases
describe('multiple placeholders mixed cases', () => {
it('replaces present values and applies defaults for missing', () => {
const out = renderTemplate('Hi {{first}} {{last|Doe}}!', { first: 'John' });
assert.strictEqual(out, 'Hi John Doe!');
});
it('throws on any missing without default in strict mode even if others have values', () => {
assert.throws(
() => renderTemplate('A {{ok}} B {{missing}}', { ok: 'K' }, { strict: true }),
(err) => err instanceof Error && /Missing value for missing/.test(err.message)
);
});
});
});
帮助开发者快速生成全面、高质量、覆盖边界情况与错误处理的单元测试,从而提高代码可靠性和开发效率。
通过提示词快速生成复杂后台逻辑的单元测试代码,节省时间并提升项目代码质量。
高效覆盖潜在边界和错误场景,协助团队发现bug并优化测试流程。
快速生成标准化测试案例模板,减少人工检查测试覆盖率的时间成本。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
半价获取高级提示词-优惠即将到期