2

ComboBox から派生したコントロールを作成し、その動作を単体テストしたいと考えています。

ただし、単体テストでは、実際のアプリケーションでの動作とは異なる動作をしているようです。

実際のアプリケーションでは、Combobox.DataSource プロパティと .Items が同期します。つまり、Combobox.DataSource を変更すると、.Items リストがすぐに自動的に更新され、DataSource の各要素の項目が表示されます。

私のテストでは、ComboBox を構築し、それにデータソースを割り当てますが、.Items リストはまったく更新されず、0 項目のままです。したがって、テストで .SelectedIndex を 0 に更新して最初の項目を選択しようとすると、ArgumentOutOfRangeException が発生します。

これは、イベント ループを開始する単体テストに Application.Run がないためですか、それともちょっとしたニシンですか?

編集: 最初のテストの詳細:

    [SetUp]
    public void SetUp()
    {
        mECB = new EnhancedComboBox();

        mECB.FormattingEnabled = true;
        mECB.Location = new System.Drawing.Point( 45, 4 );
        mECB.Name = "cboFind";
        mECB.Size = new System.Drawing.Size( 121, 21 );
        mECB.TabIndex = 3;

        mECB.AddObserver( this );

        mTestItems = new List<TestItem>();
        mTestItems.Add( new TestItem() { Value = "Billy" } );
        mTestItems.Add( new TestItem() { Value = "Bob" } );
        mTestItems.Add( new TestItem() { Value = "Blues" } );

        mECB.DataSource = mTestItems;
        mECB.Reset();

        mObservedValue = null;
    }

    [Test]
    public void Test01_UpdateObserver()
    {
        mECB.SelectedIndex = 0;
        Assert.AreEqual( "Billy", mObservedValue.Value );
    }

SelectedIndex を 0 に設定しようとすると、テストは最初の行で失敗します。ただし、実際のアプリケーションのデバッグでは、.DataSource が変更されると、.Items コレクションは常に更新されます。

確かに、テストで ComboBox を実際にレンダリングする必要はありません。レンダリングするための描画サーフェスをセットアップする必要さえありません。おそらく、私が必要とする唯一の答えは、「実際にボックスを描画する必要がない単体テストシナリオで、描画されたときと同じ方法で ComboBox を更新するにはどうすればよいですか?」ということです。

4

5 に答える 5

2

コンストラクターを呼び出すだけなので、コンボボックスの多くの機能は機能しません。たとえば、ComboBox が画面上、フォーム上に描画されると、アイテムが入力されます。これは、単体テストで構築する場合には発生しません。

なぜそのコンボボックスで単体テストを書きたいのですか?

カスタム コントロールにあるロジックを分離できませんか? たとえば、これをコントローラーに入れてテストしますか?

Items コレクションの代わりに DataSource プロパティでテストしてみませんか?

于 2009-01-26T12:16:09.013 に答える
0

ターゲットが ComboBox またはその他のコントロールである場合、これによりいくつかの問題が解決されます。

target.CreateControl();

ただし、SelectedValue に null 値を設定できませんでした。コンボ ボックスの 2 つのデータ ソースを使用してテストを行いました。1 つはデータ ソースとして、もう 1 つは選択された値にバインドされています。他のコントロールを使用すると、すべてが正常に機能します。最初はテストでもフォームを作成していましたが、テストの実行中にビルドサーバーでフォームを作成すると問題が発生します。

于 2009-03-31T13:47:29.227 に答える
0

Application.Run不在がコントロールの動作に影響を与えることはできないと確信しています

于 2009-01-26T12:13:14.273 に答える
0

項目がデータ バインドされているコンボ ボックスでも同じ問題が発生しています。私の現在の解決策は、テストでフォームを作成し、コンボ ボックスを Controls コレクションに追加してから、テストでフォームを表示することです。ちょっと醜い。私のコンボ ボックスが実際に行っていることは、一連の TimeSpan オブジェクトを一覧表示し、並べ替えて、TimeSpan 値のカスタム フォーマットを設定することだけです。また、キープレス イベントに対して特別な動作をします。すべてのデータとロジックを別のクラスに抽出しようとしましたが、理解できませんでした。おそらくより良い解決策がありますが、私がやっていることは満足のいくものです。

テストを簡単にするために、テスト コードに次のクラスを作成しました。

    class TestCombo : DurationComboBox {
        public void SimulateKeyUp(Keys keys) { base.OnKeyUp(new KeyEventArgs(keys)); }
        public DataView DataView { get { return DataSource as DataView; } }
        public IEnumerable<DataRowView> Rows() { return (DataView as IEnumerable).Cast<DataRowView>(); }
        public IEnumerable<int> Minutes() { return Rows().Select(row => (int)row["Minutes"]); }
    }

    class Target {
        public TestCombo Combo { get; private set; }
        public Form Form { get; private set; }

        public Target() {
            Combo = new TestCombo();
            Form = new Form();
            Form.Controls.Add(Combo);
            Form.Show();
        }
    }

サンプルテストは次のとおりです。

           [TestMethod()]
    public void ConstructorCreatesEmptyList() {
        Target t = new Target();
        Assert.AreEqual<int>(0, t.Combo.DataView.Count);
        Assert.AreEqual<int>(-1, t.Combo.SelectedMinutes);
        Assert.IsNull(t.Combo.SelectedItem);
    }
于 2009-02-20T06:35:38.153 に答える
0

カスタム派生コンボボックスでこれを許可するために少しハックしました:

public class EnhancedComboBox : ComboBox 
{

    [... the implementation]

    public void DoRefreshItems()
    {
        SetItemsCore(DataSource as IList);       
    }
}

このSetItemsCore関数は、提供されたリストを使用して内部アイテムをロードするように基本コンボボックスに指示します。これは、データソースが変更された後に内部で使用されるものです。

この関数は、コントロールがフォーム上にないときに呼び出されることはありません。これは、このコンポーネントが何らかの形で親フォームによって提供されているため、失敗しているCurrencyManagers およびs のチェックが多数あるためです。BindingContext

とにかく、テストでは、 andプロパティのみに依存する場合は、 andmECB.DoRefreshItems()の直後に呼び出す必要があります。データバインディングなどの他の動作は、おそらくまだ機能していません。mECB.DataSource = mTestItemsSelectedIndexItems

于 2012-05-03T17:00:47.373 に答える