- 仮説(Hypothesis)  
- 対立(Antithesis)  
- 合成(Synthesis)

2026/03/25 0:28

- 仮説(Hypothesis) - 対立(Antithesis) - 合成(Synthesis)

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

## Summary

Hegel は、複数のプログラミング言語に Hypothesis レベルの品質をもたらし、バグ検出力を高めるために Antithesis と緊密に統合された、新しいプロパティベーステストライブラリ群です。自身のプロトコルを介して軽量クライアントライブラリとして Hypothesis をラップし、言語固有のジェネレーター、コンポジット、および自動縮小プロセス(Rust の例で `Fraction::from_str("0/0")` からパニックを検出)を提供します。最初の安定版は Rust を対象としており、次に Go がリリースされ、その後 C++、OCaml、および TypeScript が続きます。Hegel は現在デベロッパープレビュー段階であり、コミュニティによるテストとフィードバックを奨励しています。

主な特徴は以下の通りです。
- **プロパティベーステスト**:ジェネレーター、コンポジット、および Hypothesis に類似した縮小機能
- **AI エージェントサポート**:Claude スキルがプロパティベーステストを自動生成し、初期のテスト作成ハードルを軽減します
- **現在の制限**:高い同時実行性や非決定的なテストに対しては対応が難しく、今後の作業では Python 依存を排除した Rust ベースサーバーと並列処理の改善を予定しています

将来の開発:
- 現在の Python 依存を置き換える Rust ベースサーバーが導入され、同時実行性が向上します
- Antithesis の Bombadil イニシアチブと統合し、Hegel のプロトコルを縮小およびファズラー統合に使用することで、分散テストインフラ全体でバグ検出力を拡大します

Rust やその他のサポート言語で開発・運用している企業や開発者にとって、Hegel を採用することでプロパティテストが効率化され、バグ検出が増加し、分散環境全体で再現可能なテスト結果を提供できます。

本文

ブログ

こんにちは。私は Hypothesis を書きました。その後、11 月に Antithesis に参加し、すぐにもう一人のコア Hypothesis メンテナである Liam DeVoe とともに作業を開始しました。避けられない結果として合成が生まれたため、本日私たちは新しいプロパティベースのテストライブラリ群、Hegel を紹介します。

Hegel は Hypothesis で見られるプロパティベーステストの品質をすべての言語に持ち込み、Antithesis とシームレスに統合してバグ検出力を高めることを目指しています。本日、Rust 用 Hegel をリリースしました。これは多数のライブラリの最初の一つです。次の 1〜2 週間で Go 用 Hegel のリリースを予定し、C++、OCaml、TypeScript 向けに既にさまざまな段階で準備が進んでいるライブラリを数か月以内に公開する計画です。

以下は Rust 用 Hegel の例です。ご興味をそそるでしょう:

#[hegel::test(test_cases = 1000)]
fn test_fraction_parse_robustness(tc: hegel::TestCase) {
    let s: String = tc.draw(generators::text());
    let _ = Fraction::from_str(&s);  // パニックを起こしてはならない
}

これは

fraction
クレートにあるバグを発見します。
from_str("0/0")
がエラー値を返す代わりにパニックします。

もしこれだけで販売トークが十分でしたら、Hegel をここで確認してください。そうでなければ、プロパティベーステスト―特に Hegel ―が非常に優れている理由と、それを使うべき理由についてもう少し説明しましょう。


プロパティベーステストとは?

上記の Rust 用 Hegel の例で見たように、プロパティベーステストは「完全な具体的テストケースを自分で提供する」代わりに、テストが通るべき値域をライブラリに指定してテストします。私たちの fraction 例では、一般的な主張として次のようになります:パーサは決してクラッシュしない;有効な結果またはエラー値のいずれかを返すだけである

このプロパティベーステストは無限に多くのテストコピーと考えることができます。各テストでは

s
を別々の文字列に置き換えます:

#[test]
fn test_fraction_parse_robustness() {
    let s: String = "0/0";
    let _ = Fraction::from_str(&s);  // パニックを起こしてはならない
}

プロパティベーステストライブラリの利点は、これらの文字列を自分で考える必要がないことです。「クラッシュしない」は最も退屈なプロパティかもしれませんが、実際には非常に有用です。Python から来たときに特に役立ちます(Python プログラムは決してクラッシュしないように書くのは驚くほど難しい)――Rust でも同様です。

次にもう少し興味深い一般的なプロパティの例を示します:

use hegel::generators::{self, Generator, integers, booleans};
use rust_decimal::Decimal;
use std::str::FromStr;

#[hegel::composite]
fn decimal_gen(tc: hegel::TestCase) -> Decimal {
    let int_part = tc.draw(integers::<i64>());
    let has_frac = tc.draw(booleans());
    if has_frac {
        let frac_digits = tc
            .draw(integers::<u32>().min_value(1).max_value(28));
        let frac_val = tc
            .draw(integers::<u64>()
                .max_value(10u64.saturating_pow(frac_digits.min(18))));
        let s = format!("{}.{:0>width$}", int_part, frac_val,
                        width = frac_digits as usize);
        Decimal::from_str(&s).unwrap_or(Decimal::from(int_part))
    } else {
        Decimal::from(int_part)
    }
}

#[hegel::test(test_cases = 1000)]
fn test_decimal_scientific_roundtrip(tc: hegel::TestCase) {
    let d = tc.draw(decimal_gen());
    let sci = format!("{:e}", d);
    let parsed = Decimal::from_scientific(&sci)
        .expect(&format!("Failed to parse {:?} from {}", sci, d));
    assert_eq!(d, parsed);
}

ここでは Hegel の「ジェネレータを組み合わせる」機能を使って

Decimal
用のカスタムジェネレータを定義しました。その後、一般的なプロパティである「ラウンドトリップ」をテストしています ― 何らかの形式に値を書き込み、再度読み込むと同じ値が得られるべきです。これはほぼすべてのプロジェクトで最も頻繁にテストされる非自明なプロパティの一つです。今回の場合、
rust_decimal
は科学的表記に変換するときにゼロを正しく扱わないというバグを発見しました。

プロパティベーステストで発見されたバグの大まかな分類は次のとおりです:

  1. ゼロを忘れた。
  2. このデータ型は呪われていて、呪いに触れてしまった。
  3. 複雑な構造的不変条件でミスした。

Antithesis では主に第 3 種類に注目していますが、実際には最初の 2 種類を解消することからプロパティベーステストの価値が得られると考えています。このタイプのバグは非常に簡単に見つかるためです。

たとえば、Unicode の呪い(報告されたバグ)に触れた例:

use heck::ToTitleCase;

#[hegel::test(test_cases = 1000)]
fn test_title_case_idempotent(tc: hegel::TestCase) {
    let s: String = tc.draw(generators::text());
    let once = s.to_title_case();
    let twice = once.to_title_case();
    assert_eq!(once, twice);
}

これは「一度タイトルケースに変換すれば、もう変更の必要はない」という直感的なプロパティをテストします。残念ながら、

ß
を描画すると失敗します。最初の
to_title_case
"SS"
にし、その後の呼び出しが
"Ss"
に変換するためです。

「複雑な構造的不変条件」の現実的な例は

im
ライブラリで Hegel が発見した既知のバグです:

#[hegel::test(test_cases = 1000)]
fn test_ordmap_get_prev(tc: hegel::TestCase) {
    // 大きいキーセットをテストするためにサイズを増やすトリック。
    let n = tc.draw(generators::integers::<usize>().max_value(200));
    let keys: Vec<i32> =
        tc.draw(generators::vecs(generators::integers()).min_size(n));

    let im_map: OrdMap<i32, i32> = keys.iter().map(|&k| (k, k)).collect();
    let bt_map: BTreeMap<i32, i32> = keys.iter().map(|&k| (k, k)).collect();

    let key = tc.draw(generators::integers::<i32>());
    let im_prev = im_map.get_prev(&key).map(|(k, v)| (*k, *v));
    let bt_prev =
        bt_map.range(..=key).next_back().map(|(&k, &v)| (k, v));

    assert_eq!(
        im_prev,
        bt_prev,
        "get_prev({}) mismatch with {} keys",
        key,
        im_map.len()
    );
}

これはあるサイズを超えると

get_prev
が誤った値を返すことを発見します。この種のテストは「モデルベーステスト」と呼ばれ、対象をテストしたい何かがあれば、同じ機能を持つ単純な実装(例:全てメモリに保持する)を「モデル」として作り、プロパティベーステストでモデルと現実が常に一致するか確認します。

プロパティベーステストは他にも多くの使い方があります。この投稿では特に効果的なテスト手法の一部を紹介しました。始める際には既存のテストをリファクタリングしてみるとよいでしょうが、こうしたテスト思考に切り替えることで上記のような例をどこでも見ることができるようになります。


Hypothesis とは?

Hypothesis は世界で最も広く使われているプロパティベーステストライブラリです。その人気は Python で書かれているために多くのユーザーが存在することが一因ですが、Python には既に他にもプロパティベーステストライブラリがありました。Hypothesis が初めて広範囲に採用された理由は、以下のような利点を持っているからです。

主なメリット:

  • 高品質ジェネレータと柔軟な構築ツール の豊富なライブラリ。
  • 内部収縮(shrinking) が非常に優れており、常に読みやすい最小例を返します。他のライブラリで起こる「無効テストケースが生成される」「手動で shrinker を書く必要がある」「収縮品質が低い」などの落とし穴を回避。
  • テストデータベース があり、失敗したテストを再実行すると同じ場所で高速に失敗します。

Hypothesis のユーモアは、他のすべてのプロパティベーステストライブラリが QuickCheck(Haskell 用)に基づいているという点です。QuickCheck は素晴らしい革新でしたが、基本的には Haskell プログラマ向けであり、正確性を求めるために多くの苦労を受け入れています。一方、Python 開発者は「正確さを得るために苦労しても構わない」という考えを持たずに Python を書いている場合がほとんどです。

Hypothesis は最初は QuickCheck のポートでしたが、時とともに独自の方向へ進化し、コードに対する「定理を書き込む」よりも「使いやすいテスト拡張」に重点を置くようになりました。この変革は Hypothesis の基盤であるモデルから派生しています。実際には、Hypothesis を作るために私(Liam と Zac Hatfield‑Dodds)たちは膨大な労力を投入しました。その結果、他のライブラリが同じレベルの競争優位性を持つことはほとんどありません。Go の Rapid ライブラリは最も信頼できるポートかもしれませんが、多くの「Hypothesis‑inspired」ライブラリはコアモデルを採用していないため、その恩恵を受けていません。

正直に言うと、新しい言語向けに同じ量の労力を投入するつもりはありません!すべての言語に Hypothesis‑レベルのプロパティベーステストライブラリが欲しいとは思っていますが、毎回それをメンテナンスし続けることは現実的ではありません。


少しクレイジーなアイデア

Antithesis に参加した際に私はこう提案しました:「Hypothesis をすべての言語で書く代わりに、他の言語が Hypothesis を簡単に利用できるようにする」と。Python バインディングで他言語ライブラリをラップすることは非常に一般的ですので、逆に行ってみませんか?

Hegel の核となるアイデアは次のとおりです:Hypothesis を実行し、その生成データ全てをソースとし、薄いクライアントライブラリでそれらを好みのターゲット言語の値に変換します。Hypothesis がすべて揃っているので、機能セットを完全に実装できます。

つまり、新しい Hegel ライブラリを立ち上げるたびに、Hegel プロトコルを実装し、ターゲット言語の適切な API を決定するだけで、選択した言語向けの高品質プロパティベーステストライブラリが完成します。実際に難しい部分は「ネイティブ感」を保つための細心の注意とセンスです。

Hypothesis‑レベルのプロパティベーステストをすべての言語で提供することに加えて、Antithesis も同時進行します。長期的には Hegel が Antithesis を実行する主要な入口点になる予定です。こうすれば、Hegel テストを書いて自前のインフラでスムーズに動かしつつ、Antithesis 上で実行してバグ検出力を高めたり、デバッグ・再現性の利点を享受できます。

短期的にはこの計画はほぼ機能しています!Hegel は高度に並列化された分散システムのテストにはまだ十分ではありません――これは Hypothesis の限界を継承した結果です。Antithesis を使えば、Hegel テストを書き、より強力な検出力が必要なら Antithesis 上で実行できます。今後数か月でさらにアップデートを予定していますので、ご期待ください。


なぜ Hegel を使うべきなのか?

私自身はバイアスがありますが、Hegel は将来のソフトウェア開発において大きな役割を果たすと確信しています。現在 AI ベースのワークフローで全てが変わる中でも、その価値は増します。

Liam が最近述べたように、プロパティベーステストは AI エージェント駆動開発が失敗しないために不可欠です。私たちが過去数十年にわたり人間主導のソフトウェア開発で成功させてきた多くの利点が、今こそさらに重要になっています。

私は AI 評価に関する作業を行っており、AI がコード評価に合格した後、プロパティベーステストを追加すると、多くの場合そのソリューションが失敗することに気付きました(これは人間が初めてコードを書いてテストを加えたときも同様です)。AI は以前よりずっと上手になりましたが、そのコードは依然として「だらしない」ため、補完ツールが必要です。

逆に言えば、プロパティベーステストへの入門障壁はこれまでのどんな時代よりも低くなっています。エージェントが実際にテストを書きやすいからです!私は告白します:Hegel で見つけたバグ例のほとんどを自分ではなく Claude が書いたものです。

コア Hegel ライブラリに加えて、プロパティベーステストを書くエージェント向けスキルも公開しています。完全に置き換えるわけではありませんが、人間が最初のテストを書くことは「データ生成について深く考える」必要があります。エージェントにその初期段階を乗り越えてもらうことは大きな勝利です。

もちろん、プロパティベーステスト自体を使うべきという主張と同じで、Hegel を特に選ぶ理由もあります。もしすでに満足できる高品質のプロパティベーステストがあるなら、Hegel はまだ初期段階です ― 最高のライブラリになることを目指していますが、完全ではありません。しかし試してみてください。Claude が既存テストを Hegel に一括変換するはずですので、自分で比較できます(もし既存テストに対して不満があればぜひ教えてください!)。

初めてプロパティベーステストを始めるなら、Hegel は最高の出発点です。Hypothesis の強力なコアを継承し、できるだけ使いやすくしました。


今後の展開

短期的に最も注力しているのは他言語向け Hegel です。Go、C++、OCaml、TypeScript はさまざまな準備段階にあります。今後数週間でこれらを公開する予定です。

ユーザーサポート、機能リクエスト、バグ報告なども増えると予想されますが、以下のような野心的計画も進行中です:

  • Python 依存を除去。現在 Hegel テスト実行時のパフォーマンス制限になっています。長期計画として Rust で二つ目の Hegel サーバーを実装する予定ですが、いつ実現するかは未定です。
  • Antithesis が得意とするワークロードに対して Hegel を強化。現在 Hypothesis が優れている従来型プロパティベーステストには適していますが、高度な並列・非決定性テストへも拡張したいです。
  • Antithesis で使用される分散システムのテストをより良くする。これは Bombadil(Antithesis の新しいオープンソースプロパティベースイニシアチブ)との統合に向けた前提条件です。最初から Bombadil が Hegel プロトコルで優れた収縮と Antithesis フューザー統合を得る予定でしたが、Oskar がプロジェクトを開始した当時はそのようなランナーがありませんでした。ギャップを埋める方法を検討しています。

ディアレクティックに参加しよう

現在 Hegel は「開発者プレビュー」状態です。Hypothesis が非常に堅牢であるため、基盤のロジックはほぼ安定していると期待していますが、まだいくつか粗さがあります。API は満足できるものですが、完全ではありません。

ぜひ Hegel を試し、発見したバグ(自分のコードでも私たちのコードでも)を教えてください!

同じ日のほかのニュース

一覧に戻る →

2026/03/25 0:29

Appleビジネス

## Japanese Translation: > **Apple Business ― デバイス管理と広告を統合したプラットフォーム** Apple は 4 月 14 日に、200 以上の地域で *Apple Business* を開始し、Apple Business Essentials、Apple Business Manager、および Apple Business Connect を置き換えます。新しいオールインワンソリューションは、組み込み型モバイルデバイス管理(MDM)と「Blueprints」を統合し、ゼロタッチ展開、自動化された Managed Apple Account の作成、従業員グループ/役割管理、アプリ配布、および Admin API を提供します。さらに、ビジネスメール、カレンダー、ディレクトリサービス、カスタムドメインサポート、iOS 26+、iPadOS 26+、macOS 26+ 向けの Apple Business アプリも付属しています。 既存顧客のデータは自動的に移行されます。 Apple Business は米国とカナダで Apple Maps 上の広告を追加(今夏開始)し、検索結果の上部および Suggested Places に表示される広告は明確にラベル付けされて透明性を保ちます。このプラットフォームには、Apple Business Connect のブランドプロファイルとロケーション機能が組み込まれており、リッチプレイスカード、ショーケース/カスタムアクション、ロケーションインサイト、ブランデッドコミュニケーション、および Tap to Pay ブランド化が含まれます。 コアサービスは全世界の新規ユーザーと既存ユーザーに対して無料で提供されます。有料オプションとして、最大 2 TB の iCloud ストレージ($0.99/ユーザー/月)と AppleCare+ for Business(デバイスあたり $6.99 またはユーザーあたり $13.99/月)が利用可能です。ゼロタッチ展開は、Apple または認定販売業者から購入したデバイスで利用でき、プライバシーモデルではユーザーの位置情報と広告インタラクションデータを Apple アカウントから分離し、オンデバイスに保存され、第三者と共有されません。

2026/03/25 6:24

害虫駆除向けの垂直型 SaaS を構築したいと思ったので、技術者として働くことにしました。

## Japanese Translation: (主要ポイントをすべて組み込む)** 著者は30 億ドルのTAMと強固な継続収益性が見えたため、害虫駆除業界へ転職しました。彼は業界最大手グループの子会社に採用され、即座にローカルブランド全体で**数十億ドル規模の売上を担当**しました。13日という記録的な期間で集中的な学習・セミナー・試験・監督付きトラック時間を経てライセンスを取得しました。 現場業務では、典型的な物流上の課題に直面しました:バッテリーがフラット、燃料カードが5週間以上遅れ、経費精算が遅い。会社のコアシステムは高度にカスタマイズされたSalesforce環境であり、オンボーディングには10個以上のモバイルアプリが必要でした。彼はトラックアイドリング、GPS、訪問時間、電話活動を通じて技術者のパフォーマンスを監視しました。最初は厳格な監視に抵抗したものの、結局は従事しました。 現場での成功により、彼は上級技術者を追跡し正式なトレーニングなしに小規模アップセルを実行したことから「潜入ボス」というニックネームを得ました。その後セールスへ転身し、アウトバウンドワークフローを構築して21日で24 k ARR契約(さらに小規模なアップセル)を確保しました。しかし、内部見積もりプロセスが複数署名と新規アカウント作成を必要とするため手間がかかり、取引損失のリスクがあることに気付きました。 セールスチームは10年以上の経験を持つベテラン担当者で構成されており、それぞれ800k–1.2M ARRを生成し低いチャーン率を維持しています。彼らの文化は変化に抵抗が強く、エグジットインタビュー後、マネージャーから自分自身の会社を立ち上げるよう提案されました。 今後、著者はローカルニッチオペレーターを取得し、専用ツールを開発し、見積もり・オンボーディング・監視を統合したスケーラブルなプラットフォームを構築する計画です。このモデルにより現場技術者とセールス担当者の効率が向上し、チャーンが減少し、収益獲得が加速し、害虫駆除業界で競争力のダイナミクスが変わる可能性があります。

2026/03/24 21:06

HNに知らせてください:PyPI 上の Litellm 1.82.7 と 1.82.8 が改ざんされていること。

## 日本語訳: > PyPI の wheel **`litellm==1.82.8`** には、悪意のある `.pth` ファイル(`litellm_init.pth`、34 628 バイト)が含まれており、このファイルは `litellm` をインポートしなくても、Python インタープリターが起動するたびに自動的に実行されます。 > 隠されたスクリプトは二重 Base64 エンコードされたペイロードを実行し、ホストから認証情報(SSH キー、クラウドプロバイダーのクレデンシャル、Git の設定、Docker 設定、データベースパスワード、暗号ウォレットの秘密鍵など)を収集します。取得したデータは一時ファイルに書き込まれ、その後ランダムな AES‑256 キーで暗号化されます。AES キー自体はハードコードされた 4096 ビット公開鍵(キーは `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A...` から始まります)を使って RSA 暗号化されています。 > 暗号化されたアーカイブ(`tpcp.tar.gz`)は **`https://models.litellm.cloud/`** に POST されます。 > この脆弱性は **2026‑03‑24** に、Ubuntu 24.04 の Docker コンテナで Python 3.13 を実行している環境で発見され、影響を受けたのはバージョン 1.82.8 だけが確認されています(他のリリースも脆弱になっている可能性があります)。 > PyPI 管理者はこの wheel を直ちに削除または取り下げるべきです。`litellm==1.82.8` をインストールしたユーザーは、`site‑packages/` 内の怪しい `.pth` ファイルを確認し、漏洩した認証情報をローテーションし、CI/CD パイプラインが侵害されていないか監査してください。この脆弱なバージョンを使用していたシステム(ローカル開発マシン、Docker コンテナ、本番サーバー、自動ビルドシステムなど)は、多数の組織にわたる幅広い秘密情報が漏洩した可能性があります。