gem をプッシュするスクリプトをテストするにはどうすればよいですか?

概要

このスクリプトがあります:

#!/usr/bin/env ruby
# frozen_string_literal: true

if ARGV.any?
  puts "USAGE: release"
  exit
end

def system!(command)
  puts command
  system(command, exception: true)
end

File.delete(*Dir["*.gem"])
system!("gem build")
system!("gem push *.gem")
File.delete(*Dir["*.gem"])

私はそれを単にリリースと呼んでいます (これは dorian-release gem の一部です)。

テストしようとしていますが、最善の方法がわかりません。chatgpt はスタブを提案しますが、実際には何もテストしません。

Rubygems への HTTP リクエストをモックしたいのですが、サブコマンドなのでやり方がわかりません。

何か案が?

解決策

ダメダメダメ!アプリケーションが意図したシステム変更を達成したかどうかを確認するために、ある種の統合テストを実行することは有効ですが、単体テスト、機能テスト、および統合テストは、他のライブラリの内部をテストすべきではありません。ここで目標を再考する必要があります。

より明確な例として、インタプリタの内部に取り組んでいない限り、Kernel#puts がどのように動作するかをテストすべきではありません。ただし、それを検証するためのユースケースや、期待する場所を指していること、さらには出力がストリームには、期待した正しい補間出力が含まれています。 Kernel#puts 自体が機能するかどうかをテストすることは、テストの焦点であってはなりません。

同様に、gem プッシュによって gem が RubyGems またはテスト サーバーにプッシュされるようにするためには、複雑なことは何も必要ありません。デバッグに深く関わっていない限り、本当に知る必要があるのは、Gem が公開されたかどうかだけです。 gem Push が正しい終了ステータスを返したり、例外を発生したりすることを信頼できない場合は、おそらくそうすべきです。これは Ruby エコシステムの広く使用されている部分であり、ファイアウォール ルールやファイアウォール ルールを検証するためのプロキシ テストのようなものであるためです。同様のものです。サーバーをチェックして、新しい gem バージョンが公開されているかどうかを確認する必要があります。

実際に必要な複雑さのレベルに応じて、さまざまな方法でこれを行うことができます。できるだけシンプルにしたいと思います。そうしないと、テストの依存関係をテストするというウサギの穴に落ちてしまうことになりますが、これは自虐的で一般的には不要です。単純なものから複雑なものの順に:

RubyGems HTTP(S) 呼び出しの内部をトレースすることは、RubyGems 開発者でない限り、通常は行うべきではありません。他の人にとっては、HTTP(S) 呼び出しがネットワーク レベルまたはプロトコル レベルで失敗する理由を確認するために、テスト プロキシを実行するよりも深く調査している場合は、不必要なオーバーヘッドが発生していることになります。アプリケーション層でアプリケーションをテストし、共通の外部ライブラリに依存している場合は、そのテストを信頼して、それらが意図したとおりに動作するかどうかを検証してください。