unit-test-utility-methods
ユーティリティクラス・静的メソッド・ヘルパー関数のテストパターンを提供します。純粋関数・null処理・エッジケース・境界条件の検証に対応し、文字列ユーティリティ・数値ユーティリティ・バリデーター・コレクションヘルパーに対してAssertJアサーションや`@ParameterizedTest`を生成します。ユーティリティコードの正確性を検証したい場合や、静的メソッド・ヘルパー関数のテストを作成する際に使用してください。
description の原文を見る
Provides patterns for testing utility classes, static methods, and helper functions. Validates pure functions, null handling, edge cases, and boundary conditions. Generates AssertJ assertions and @ParameterizedTest for string utils, math utils, validators, and collection helpers. Use when testing utils, test helpers, helper functions, static methods, or verifying utility code correctness.
SKILL.md 本文
ユーティリティクラスと静的メソッドのユニットテスト
概要
このスキルは、静的ヘルパーメソッドと純粋関数を持つユーティリティクラスのテストを生成します。null処理、エッジケース、境界条件、および文字列操作、計算、データ検証、コレクション処理などの一般的なユーティリティをテストするためのパターンを提供します。純粋関数はモックが不要です。
使用するべき場合
このスキルを使用するのは、以下の場合です:
- 静的メソッドを持つユーティリティ/ヘルパークラスのテストを作成する場合
- 状態や副作用のない純粋関数をテストする場合
- 文字列操作、フォーマット、変換ユーティリティをテストする場合
- 計算、変換、数学ヘルパー関数をテストする場合
- データ検証およびフォーマッターユーティリティをテストする場合
- ユーティリティコード内のnull/空入力処理を検証する場合
- コレクションまたは配列ヘルパーメソッドをテストする場合
手順
- テストクラスを作成: ユーティリティの名前で命名します(例:
StringUtilsTest) - 正常系をテスト: 有効な入力と予期される出力
- エッジケースをテスト: null、空、空白、単一要素
- 境界条件をテスト: 最大/最小値、大きな数、精度
- 説明的な名前を使用:
test1ではなくshouldCapitalizeFirstLetter - AssertJを使用: 読みやすく、チェーン可能なアサーション
@ParameterizedTestを使用: 複数の類似入力の場合(references/parameterized-tests.mdを参照)- モックを避ける: 純粋ユーティリティはモックが不要
例
基本的な静的ユーティリティテスト
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;
class StringUtilsTest {
@Test
void shouldCapitalizeFirstLetter() {
assertThat(StringUtils.capitalize("hello")).isEqualTo("Hello");
}
@Test
void shouldReturnNullForNullInput() {
assertThat(StringUtils.capitalize(null)).isNull();
}
@Test
void shouldHandleEmptyString() {
assertThat(StringUtils.capitalize("")).isEmpty();
}
@Test
void shouldHandleSingleCharacter() {
assertThat(StringUtils.capitalize("a")).isEqualTo("A");
}
}
包括的な例:isEmpty実装
// Input: public static boolean isEmpty(String str)
// { return str == null || str.trim().isEmpty(); }
class StringUtilsTest {
@Test
void shouldReturnTrueForNullString() {
assertThat(StringUtils.isEmpty(null)).isTrue();
}
@Test
void shouldReturnTrueForEmptyString() {
assertThat(StringUtils.isEmpty("")).isTrue();
}
@Test
void shouldReturnTrueForWhitespaceOnly() {
assertThat(StringUtils.isEmpty(" ")).isTrue();
}
@Test
void shouldReturnFalseForNonEmptyString() {
assertThat(StringUtils.isEmpty("hello")).isFalse();
}
}
Null安全ユーティリティ
class NullSafeUtilsTest {
@Test
void shouldReturnDefaultWhenNull() {
assertThat(NullSafeUtils.getOrDefault(null, "default")).isEqualTo("default");
}
@Test
void shouldReturnValueWhenNotNull() {
assertThat(NullSafeUtils.getOrDefault("value", "default")).isEqualTo("value");
}
@Test
void shouldReturnFalseWhenBlank() {
assertThat(NullSafeUtils.isNotBlank(null)).isFalse();
assertThat(NullSafeUtils.isNotBlank(" ")).isFalse();
}
}
数学/計算ユーティリティ
class MathUtilsTest {
@Test
void shouldCalculatePercentage() {
assertThat(MathUtils.percentage(25, 100)).isEqualTo(25.0);
}
@Test
void shouldHandleZeroDivisor() {
assertThat(MathUtils.percentage(50, 0)).isZero();
}
@Test
void shouldRoundToDecimalPlaces() {
assertThat(MathUtils.round(3.14159, 2)).isEqualTo(3.14);
}
@Test
void shouldHandleFloatingPointWithTolerance() {
assertThat(MathUtils.multiply(0.1, 0.2))
.isCloseTo(0.02, within(0.0001));
}
}
コレクションユーティリティ
class CollectionUtilsTest {
@Test
void shouldFilterList() {
List<Integer> result = CollectionUtils.filter(List.of(1, 2, 3, 4), n -> n % 2 == 0);
assertThat(result).containsExactly(2, 4);
}
@Test
void shouldHandleNullList() {
assertThat(CollectionUtils.filter(null, n -> true)).isEmpty();
}
@Test
void shouldJoinWithSeparator() {
assertThat(CollectionUtils.join(List.of("a", "b", "c"), "-")).isEqualTo("a-b-c");
}
@Test
void shouldDeduplicateList() {
assertThat(CollectionUtils.deduplicate(List.of("a", "b", "a")))
.containsExactlyInAnyOrder("a", "b");
}
}
データ検証ユーティリティ
class ValidatorUtilsTest {
@Test
void shouldValidateEmailFormat() {
assertThat(ValidatorUtils.isValidEmail("user@example.com")).isTrue();
assertThat(ValidatorUtils.isValidEmail("invalid")).isFalse();
}
@Test
void shouldValidateUrlFormat() {
assertThat(ValidatorUtils.isValidUrl("https://example.com")).isTrue();
assertThat(ValidatorUtils.isValidUrl("not a url")).isFalse();
}
@Test
void shouldValidateCreditCard() {
assertThat(ValidatorUtils.isValidCreditCard("4532015112830366")).isTrue();
assertThat(ValidatorUtils.isValidCreditCard("1234567890123456")).isFalse();
}
}
Clock依存を持つユーティリティ(まれ)
@ExtendWith(MockitoExtension.class)
class DateUtilsTest {
@Mock
private Clock clock;
@Test
void shouldGetDateFromClock() {
when(clock.instant()).thenReturn(Instant.parse("2024-01-15T10:00:00Z"));
assertThat(DateUtils.today(clock)).isEqualTo(LocalDate.of(2024, 1, 15));
}
}
ベストプラクティス
- 純粋関数のみをテスト - 副作用や状態の依存がない
- 正常系とエッジケースをカバー - null、空、空白、極端な値
- 説明的なテスト名を使用 -
shouldReturnNullWhenInputIsNull - 複数の類似入力には
@ParameterizedTestを使用 (references/parameterized-tests.mdを参照) - 境界条件をテスト - 最小/最大値、オーバーフロー、精度
- 純粋関数をモックしない - Clock のような外部依存関係のみモック
- テストを独立させる - テスト間に順序の依存性がない
制約と警告
- 静的メソッドをモックしない: 絶対に必要な場合のみリフレクションユーティリティを使用
- 純粋関数の要件: ステートフルなユーティリティはテストが困難です。不変性を優先してください
- 浮動小数点精度: 厳密な等価性を使用しないでください。
isCloseTo(delta)を使用してください - null処理の一貫性: ユーティリティが null を返すか例外を発生させるかを決定し、それに応じてテストしてください
- スレッド安全性: 静的ユーティリティはスレッドセーフである必要があります。同時実行動作を別途検証してください
- 不変入力: ユーティリティが入力パラメータを変更するかどうかを記録してください
- エッジケースリファレンス: 境界テストパターンについては
references/edge-cases.mdを参照
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- giuseppe-trisciuoglio
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/giuseppe-trisciuoglio/developer-kit / ライセンス: MIT
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。