4

私のアプリケーションの1つに、ユーザー入力を担当するクラスがあります。デフォルトの入力方法はコンソール(キーボード)です。それが正しいことを確認するために、いくつかの単体テストを作成したいと思います。

ユニットテストにgoogle-testフレームワークを使用することを検討しています。これにより、すべてのテストを簡単に自動化できます。ただし、コンソール入力のテストを自動化する方法がわかりません。

キーボードでのユーザー入力をシミュレートする方法はありますか?または、テスト入力を手動で入力する必要がありますか?または、おそらくリダイレ​​クトstdinしますか(コード内または単体テストの実行時にパイプによって)?

編集:ユーザー入力にGNUreadlineを使用することを計画しています。現時点では、このライブラリの入力ストリームをリダイレクトする方法がわかりません。おそらく、他の誰かがこれを経験したことがありますか?

4

7 に答える 7

3

あなたはexpectを使うことができます。

于 2009-08-21T01:55:20.063 に答える
3

基本的に、クラスはstdinだけでなく、ランダムな入力ストリームを使用できる必要があります(まだ使用できない場合は、リファクタリングする必要があります)。

その後、カスタムデータを使用してモックストリームを配置し、ユーザー入力をシミュレートすることができます。

于 2009-08-21T01:55:21.170 に答える
1

ユーザー入力にGNUreadlineを使用することを計画しています。現時点では、このライブラリの入力ストリームをリダイレクトする方法がわかりません

使用するreadline機能に一致するメンバーで抽象クラスを作成します。readline APIに対して直接ではなく、この抽象クラスに対してプログラムします。依存性注入を使用して、このクラスのインスタンスをそれを必要とするコードに取得します。

次に、このクラスの2つの実装を作成できます。1つは単にreadlineライブラリをラップするもので、もう1つは単体テストで使用できるモック実装です。モック実装には、ユーザーのシミュレーションを容易にする追加のメンバーが含まれます。

于 2009-08-21T09:14:34.073 に答える
1

入力をモックします。

于 2009-08-21T01:50:37.383 に答える
1

プラットフォームが.NETの場合、これを行う1つの方法があります

于 2009-08-21T07:13:18.530 に答える
0

コンソールの場合、私は常にそれを自分の実装でラップします。

単体テストに関係するすべてのサードパーティコントロールにラッパーとインターフェイスを使用すると、分離フレームワーク(Rhino Mocksなど)の操作が非常に簡単になります。これにより、テストを制御でき、コードの依存関係を明示的に定義できます。コンソールの新機能が必要なので、ラッパーインターフェイスに追加するだけです。インターフェイスの肥大化に関する問題はまだ発生していません...

public interface IConsoleShim
{
    void WriteLine(string message);
    ConsoleKeyInfo ReadKey();
}
public class ConsoleShim : IConsoleShim
{
    public void WriteLine(string message)
    {
        Console.WriteLine(message);
    }
    public ConsoleKeyInfo ReadKey()
    {
        return Console.ReadKey();
    }
}

これが実際のテストです

[NUnit.Framework.Test]
public void Run_writes_to_console_100_times_waits_for_keypress()
{
    // arrange
    Rhino.Mocks.MockRepository mocks = new Rhino.Mocks.MockRepository();
    IConsoleShim consoleMock = mocks.StrictMock<IConsoleShim>();
    Program program = new Program(consoleMock);
    int expected = 100;

    // VerifyAll automatically called
    Rhino.Mocks.With.Mocks(mocks).Expecting(() =>
        {
            Rhino.Mocks.Expect.Call(() => consoleMock.WriteLine("")).IgnoreArguments().Repeat.Times(expected);
            Rhino.Mocks.Expect.Call(consoleMock.ReadKey()).Return(new ConsoleKeyInfo());
        });

    //act
    program.Run();
}
于 2009-08-21T15:14:54.473 に答える
0

.NET / C#の場合、この質問にあるOptionsクラスまたはバリエーションを使用できます。すべてのコマンドがデリゲートにマップされているため、デリゲートの最後で各メソッドの単体テストを実行して、不明なコマンドを簡単に見つけることができます。

MyHandler handler = new MyHandler()
CommandOptions options = new CommandOptions();

// Put this in the test Setup
options.Add("show", handler.Show)
        .Add("connect", v => handler.Connect(v))
        .Add("dir", handler.Dir);

if (!options.Parse(args))
   Assert.Fail(string.Format("{0} was not recognised.",args))

MyHandlerクラスは次のようになります。

public class MyHandler
{
    public void Show() { }
    public void Connect(string[] args){}
    public void Dir() {}
}
于 2009-08-21T07:33:41.157 に答える