129

UserC# を使用して、ユーザー名、パスワード、アクティブ フラグ、名、姓、フルネームなどを持つ クラスが必要です。

ユーザーを認証して保存する方法が必要です。メソッドのテストを書くだけですか?また、プロパティは .Net の getter および setter であるため、プロパティのテストについても心配する必要がありますか?

4

36 に答える 36

133

これに対する多くの素晴らしい回答も私の質問にあります:「TDDの開始-課題?解決策?推奨事項?

また、私のブログ投稿(私の質問に部分的に触発された)を参照することをお勧めします。それについていくつかの良いフィードバックがあります。すなわち:

どこから始めたらいいのかわからない?

  • 新たに始めましょう。新しいコードを書くときだけ、テストを書くことを考えてください。これは、古いコードの再加工、または完全に新しい機能である可能性があります。
  • 簡単に始めましょう。TDD風であるだけでなく、テストフレームワークに頭を悩ませようとしないでください。Debug.Assertは正常に機能します。出発点として使用してください。プロジェクトを混乱させたり、依存関係を作成したりすることはありません。
  • ポジティブに始めましょう。あなたは自分の技術を改善しようとしています、それについて気分がいいです。私はそこにたくさんの開発者が停滞し、自分自身を改善するために新しいことを試みないことを喜んでいるのを見てきました。あなたは正しいことをしています、これを覚えておいてください、そしてそれはあなたが諦めるのを防ぐのを助けます。
  • チャレンジの準備を始めましょう。テストを開始するのは非常に困難です。挑戦を期待しますが、覚えておいてください–挑戦は克服することができます。

あなたが期待するものだけをテストする

私が最初に始めたとき、私は起こりうるすべての可能な問題を理解しようと常にそこに座っていて、それをテストして修正しようとしたので、本当の問題を抱えていました。これは頭​​痛の種への手っ取り早い方法です。テストは実際のYAGNIプロセスである必要があります。問題があることがわかっている場合は、そのテストを作成します。それ以外の場合は、気にしないでください。

1つだけテストする

各テストケースは、1つのことだけをテストする必要があります。テストケース名に「and」を入れていることに気付いた場合は、何か問題があります。

これが「ゲッターとセッター」から先に進むことができることを意味することを願っています:)

于 2008-09-15T13:18:40.780 に答える
63

言語ではなく、コードをテストしてください。

次のような単体テスト:

Integer i = new Integer(7);
assert (i.instanceOf(integer));

instanceofコンパイラを作成していて、メソッドが機能しない可能性がゼロではない場合にのみ役立ちます。

強制するために言語に依存できるものをテストしないでください。あなたの場合、私はあなたの認証方法と保存方法に焦点を当てます-そして、それらのフィールドのいずれかまたはすべてでnull値を適切に処理できることを確認するテストを作成します.

于 2008-09-15T13:09:07.760 に答える
38

これでユニットテストが始まり、とても幸せになりました

ユニットテストを始めたばかりです。長い間、始めたほうがいいと思っていましたが、どうやって始めればいいのか、もっと重要なのは何をテストすればいいのかわからなかったのです。

次に、会計プログラムの重要なコードを書き直す必要がありました。この部分は、さまざまなシナリオが含まれるため、非常に複雑でした。私が話しているのは、会計システムにすでに入力されている売上および/または購入の請求書を支払う方法です。

非常に多くの異なる支払いオプションがあったので、私はそれをコーディングし始める方法を知りませんでした。請求書は100ドルになる可能性がありますが、顧客は99ドルしか送金しませんでした。顧客に売上請求書を送信したが、その顧客からも購入した可能性があります。それであなたは彼を300ドルで売りましたが、100ドルで買いました。残高を決済するために、顧客が200ドルを支払うことを期待できます。また、500ドルで販売したが、顧客が250ドルしか支払っていない場合はどうでしょうか。

そのため、1つのシナリオは完全に機能するが、他のタイプの請求と支払いの組み合わせでは間違っているという多くの可能性で解決する非常に複雑な問題がありました。

ここで、ユニットテストが役に立ちました。

私は(テストコード内に)販売と購入の両方の請求書のリストを作成する方法を書き始めました。次に、実際の支払いを作成するための2番目の方法を作成しました。通常、ユーザーはユーザーインターフェイスを介してその情報を入力します。

次に、最初のTestMethodを作成し、支払い割引なしで1つの請求書の非常に単純な支払いをテストしました。システム内のすべてのアクションは、銀行の支払いがデータベースに保存されるときに発生します。ご覧のとおり、請求書を作成し、支払い(銀行取引)を作成して、取引をディスクに保存しました。私の主張では、銀行の取引とリンクされた請求書に最終的に正しい番号を入れる必要があります。取引後の支払い回数、支払い額、割引額、請求書の残高を確認します。

テストを実行した後、データベースにアクセスして、期待したものがそこにあるかどうかを再確認しました。

テストを書いた後、支払い方法(BankHeaderクラスの一部)のコーディングを開始しました。コーディングでは、最初のテストに合格するためのコードだけを気にしました。他のもっと複雑なシナリオについてはまだ考えていませんでした。

最初のテストを実行し、テストに合格するまで小さなバグを修正しました。

それから私は2番目のテストを書き始めました。今回は支払い割引を使って作業しました。テストを作成した後、割引をサポートするように支払い方法を変更しました。

支払い割引で正しさをテストしながら、単純な支払いもテストしました。もちろん、両方のテストに合格する必要があります。

次に、より複雑なシナリオに取り組みました。

1)新しいシナリオを考えてください

2)そのシナリオのテストを作成します

3)その単一のテストを実行して、合格するかどうかを確認します

4)合格しなかった場合は、コードが合格するまでデバッグおよび変更します。

5)コードを変更している間、私はすべてのテストを実行し続けました

このようにして、非常に複雑な支払い方法を作成することができました。ユニットテストなしでは、コーディングを開始する方法がわかりませんでした。問題は圧倒的であるように見えました。テストでは、単純な方法から始めて、より単純なシナリオでも機能することを保証しながら、段階的に拡張することができました。

単体テストを使用すると、コーディングに数日(または数週間)節約でき、メソッドの正確性が多かれ少なかれ保証されると確信しています。

後で新しいシナリオを考えた場合は、それをテストに追加して、機能しているかどうかを確認できます。そうでない場合は、コードを変更できますが、他のシナリオが引き続き正しく機能していることを確認してください。これにより、メンテナンスとバグ修正の段階で何日も節約できます。

はい、テストされたコードでさえ、ユーザーがあなたが思いもよらなかったことをしたり、彼がやることを妨げたりした場合、まだバグがある可能性があります

以下は、支払い方法をテストするために作成したテストのほんの一部です。

public class TestPayments
{
    InvoiceDiaryHeader invoiceHeader = null;
    InvoiceDiaryDetail invoiceDetail = null;
    BankCashDiaryHeader bankHeader = null;
    BankCashDiaryDetail bankDetail = null;



    public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date)
    {
        ......
        ......
    }

    public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount)
    {
       ......
       ......
       ......
    }


    [TestMethod]
    public void TestSingleSalesPaymentNoDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 1, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSingleSalesPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 2, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    [ExpectedException(typeof(ApplicationException))]
    public void TestDuplicateInvoiceNumber()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("100", true, 2, "01-09-2008"));
        list.Add(CreateSales("200", true, 2, "01-09-2008"));

        bankHeader = CreateMultiplePayments(list, 3, 300, 0);
        bankHeader.Save();
        Assert.Fail("expected an ApplicationException");
    }

    [TestMethod]
    public void TestMultipleSalesPaymentWithPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 11, "01-09-2008"));
        list.Add(CreateSales("400", true, 12, "02-09-2008"));
        list.Add(CreateSales("600", true, 13, "03-09-2008"));
        list.Add(CreateSales("25,40", true, 14, "04-09-2008"));

        bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount);
        Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount);

        Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount);

        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSettlement()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales
        list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase

        bankHeader = CreateMultiplePayments(list, 22, 200, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
    }
于 2008-09-16T03:52:41.787 に答える
13

それらが本当に些細なものであれば、わざわざテストする必要はありません。たとえば、このように実装されている場合。

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

一方、巧妙なことをしている場合 (getter/setter でパスワードを暗号化および復号化するなど)、テストしてみてください。

于 2008-09-15T13:10:12.360 に答える
10

ルールは、作成したすべてのロジックをテストする必要があるということです。ゲッターとセッターに特定の機能を実装した場合は、テストする価値があると思います。一部のプライベート フィールドにのみ値を割り当てる場合は、気にしないでください。

于 2008-09-15T13:07:50.790 に答える
6

この質問は、どのメソッドがテストされ、どのメソッドがテストされないかについて、どこで線を引くかという問題のようです。

値の割り当てのためのセッターとゲッターは、一貫性と将来の成長を念頭に置いて作成されており、いつかセッター/ゲッターがより複雑な操作に進化する可能性があることを予測しています。一貫性と将来の成長のためにも、これらのメソッドの単体テストを配置することは理にかなっています。

コードの信頼性は、特に追加機能を追加するための変更が行われている間は、主要な目標です。セッター/ゲッターをテスト方法論に含めたために解雇された人はいませんが、単純なセット/ゲットラッパーであることに最後に気付いた、または思い出すことができるメソッドをテストしたいと思った人がいると確信していますが、それはそうではありませんでしたケースが長くなります。

おそらく、チームの別のメンバーが set/get メソッドを拡張して、テストが必要なロジックを含めたのに、テストを作成しなかった可能性があります。しかし今、あなたのコードはこれらのメソッドを呼び出しており、それらが変更されていて詳細なテストが必要であることを認識していません。開発と QA で行うテストは欠陥をトリガーしませんが、リリース初日の実際のビジネス データは欠陥をトリガーします。トリガーします。

2 人のチームメイトは、失敗する可能性があるが単体テストでカバーされていないロジックを含むようにセット/取得がモーフィングされたときに、誰がボールを落として単体テストに失敗したかについて議論します。最初に set/gets を作成したチームメイトは、テストが単純な set/gets で初日から実装されていれば、このクリーンから抜け出すのがより簡単になります。

私の意見では、すべてのメソッドを単体テストでカバーする「無駄な」時間は、ほんの些細なものであっても、将来の頭痛の種、お金/ビジネスの評判の喪失、誰かの仕事の喪失を救うかもしれません。

そして、単純なメソッドをユニットテストでラップしたという事実は、そのジュニアチームメイトが単純なメソッドを重要なメソッドに変更し、テストを更新するよう促したときに見られる可能性があり、欠陥が含まれていたため、誰も問題を抱えていません。生産に至るまで。

私たちのコーディング方法と、コードから見られる規律は、他の人を助けることができます。

于 2015-03-21T12:55:23.480 に答える
4

別の標準的な答え。これは、ロン・ジェフリーズからだと思います。

作業したいコードのみをテストしてください。

于 2008-09-15T19:04:27.953 に答える
3

ツールキットまたはオープン ソース タイプのプロジェクトになる可能性のある単純なモジュールの場合は、簡単なゲッターとセッターを含めて、可能な限りテストする必要があります。覚えておきたいことは、特定のモジュールを作成するときに単体テストを生成することは、非常に単純で簡単だということです。ゲッターとセッターの追加は最小限のコードであり、あまり考えなくても処理できます。ただし、コードが大規模なシステムに配置されると、この余分な作業により、基本クラスの型の変更など、基になるシステムの変更から保護できます。すべてをテストすることは、回帰を完全にするための最良の方法です。

于 2008-09-15T14:10:00.767 に答える
3

すべてをテストする必要があります。現在、getter と setter がありますが、いずれそれらを多少変更して、検証などを行う可能性があります。今日作成したテストは、すべてが通常どおり機能し続けることを確認するために明日使用されます。テストを書くときは、「今は些細なことだ」などの考慮事項を忘れる必要があります。アジャイルまたはテスト駆動のコンテキストでは、将来のリファクタリングを想定してテストする必要があります。また、非常に長い文字列やその他の「悪い」コンテンツなど、非常に奇妙な値を入力しようとしましたか? まあ、あなたのコードが将来どれほどひどく悪用される可能性があるかを決して想定しないでください。

一般的に、大規模なユーザー テストを作成することは一方的に行われ、疲れます。一方で、アプリケーションがどのように機能するべきかについて常に貴重な洞察を与えてくれ、簡単な (そして誤った) 仮定 (ユーザー名は常に 1000 文字未満であるなど) を捨てるのに役立ちます。

于 2008-09-15T14:01:08.587 に答える
3

ボイラープレート コードのテストは時間の無駄ですが、Slavo が言うように、getter/setter に副作用を追加する場合は、その機能に付随するテストを作成する必要があります。

テスト駆動型開発を行っている場合は、最初にコントラクト (インターフェースなど) を作成し、次にそのインターフェースを実行するテストを作成して、期待される結果/動作を文書化する必要があります。次に、単体テストのコードに触れずに、メソッド自体を記述します。最後に、コード カバレッジ ツールを入手して、テストがコード内のすべてのロジック パスを実行することを確認します。

于 2008-09-15T13:12:21.590 に答える
3

getter や setter のように、プライベート フィールドを設定する以外に特別な動作を持たない、本当に些細なコードをテストするのはやり過ぎです。3.0 では、C# には、コンパイラがプライベート フィールドを処理する構文糖衣さえあるため、それをプログラムする必要はありません。

私は通常、自分のクラスに期待する動作を検証する非常に単純なテストをたくさん書いています。たとえそれが2つの数字を足すような単純なものであっても. 簡単なテストを書くことと、数行のコードを書くことを頻繁に切り替えます。その理由は、考えもしなかったものを壊してしまうことを恐れることなく、コードを変更できるからです。

于 2008-09-15T13:14:54.190 に答える
2

一般に、メソッドが特定の値に対してのみ定義されている場合は、許容範囲を超えた値をテストします。言い換えると、メソッドが想定どおりに機能することを確認しますが、それ以上のことはしません。これは重要です。失敗するときは、早く失敗したいからです。

継承階層では、必ずLSP準拠をテストしてください。

後で検証を行う予定がない限り、デフォルトのゲッターとセッターをテストすることは、私にはあまり役に立ちません。

于 2008-09-15T13:14:59.633 に答える
2

壊れる可能性があると思われる場合は、そのためのテストを作成してください。私は通常、セッター/ゲッターをテストしませんが、名前と姓を連結する User.Name 用に作成するとしましょう。テストを作成して、誰かが姓と名の順序を変更した場合、少なくとも彼は知っているでしょう彼はテストされた何かを変更しました。

于 2008-09-15T13:49:52.937 に答える
2

標準的な答えは、「壊れる可能性があるものは何でもテストする」です。プロパティが壊れないことが確実な場合は、テストしないでください。

そして、何かが壊れている (バグを見つけた) ことが判明したら、それは明らかにそれをテストする必要があることを意味します。バグを再現するテストを書き、それが失敗するのを見て、バグを修正して、テストがパスするのを見てください。

于 2008-09-15T13:51:14.227 に答える
2

ゲッターとセッターの単体テストを作成しても問題はありません。現時点では、内部でフィールドの get/set を行っているだけかもしれませんが、将来的には検証ロジックやプロパティ間の依存関係をテストする必要があるかもしれません。それについて考えている間に今それを書く方が簡単です。

于 2008-09-15T13:08:10.073 に答える
1

コードのテストが必要な場所を正しく推測することは可能ですが、一般的に、この推測を裏付けるにはメトリックが必要だと思います。私の見解では、単体テストはコードカバレッジメトリックと密接に関連しています。

多くのテストを含むコードですが、カバレッジが小さい場合は十分にテストされていません。とは言うものの、100%カバレッジであるが、境界とエラーのケースをテストしていないコードも素晴らしいものではありません。

高カバレッジ(最小90%)と可変入力データのバランスが必要です。

「ガベージイン」をテストすることを忘れないでください!

また、ユニットテストは、失敗をチェックしない限り、ユニットテストではありません。アサートがないか、既知の例外でマークされている単体テストは、実行時にコードが停止しないことをテストするだけです。

テストは、失敗や予期しない/不要なデータを常に報告するように設計する必要があります。

于 2008-09-15T14:51:09.747 に答える
1

簡単な操作だけでゲッターとセッターをテストするのはばかげていると思います。個人的には、使用パターンをカバーするために複雑な単体テストを作成することはありません。私は、通常の実行動作と考えられる限りのエラーケースを処理したことを確認するために、十分なテストを作成しようとしています。バグレポートへの応答として、より多くの単体テストを作成します。単体テストを使用して、コードが要件を満たしていることを確認し、将来の変更を容易にします。何かを壊すとテストが失敗することを知っているとき、私はコードを変更することをもっと喜んで感じます。

于 2008-09-15T13:16:17.277 に答える
1

それは私たちのコードをより良くします...期間!

私たちソフトウェア開発者がテスト駆動開発を行うときに忘れていることの1つは、私たちの行動の背後にある目的です。プロダクションコードがすでに配置された後に単体テストが作成されている場合、テストの値は大幅に低下します(ただし、完全に失われるわけではありません)。

単体テストの真の精神では、これらのテストは主にコードを「テスト」するためのものではありません。または、90%〜100%優れたコードカバレッジを取得します。これらはすべて、最初にテストを作成することの利点です。大きな見返りは、TDDの自然なプロセスにより、プロダクションコードの終わりがはるかに良く記述されることです。

この考えをよりよく伝えるのを助けるために、以下は読むのに役立つかもしれません:

ユニットテストの欠陥のある理論目的の
あるソフトウェア開発

より多くの単体テストを作成するという行為が、より高品質の製品を入手するのに役立つと思われる場合は、テスト駆動開発のカーゴカルトに苦しんでいる可能性があります。

于 2008-09-15T15:08:31.797 に答える
1

Authenticate メソッドと Save メソッドに対して複数のテストを作成することをお勧めします。成功ケース (すべてのパラメーターが提供されている、すべてのスペルが正しいなど) に加えて、さまざまな失敗ケース (パラメーターが正しくないか欠落している、該当する場合はデータベース接続が利用できないなど) のテストを行うことをお勧めします。NUnitを参考にして、C# での Pragmatic Unit Testingをお勧めします。

他の人が述べているように、ゲッターとセッターに条件付きロジックがない限り、ゲッターとセッターの単体テストはやり過ぎです。

于 2008-09-15T14:09:04.997 に答える
1

GUIインターフェイスの外でテストできるコードを書いているものは何でもテストを書きます。

通常、私が作成したロジックには、別の層またはビジネス ロジック レイヤー内に配置したビジネス ロジックが含まれます。

そうすれば、何かを行うためのテストを書くのは簡単です。

最初のパスとして、「ビジネス ロジック レイヤー」の各パブリック メソッドの単体テストを記述します。

このようなクラスがあった場合:

   public class AccountService
    {
        public void DebitAccount(int accountNumber, double amount)
        {

        }

        public void CreditAccount(int accountNumber, double amount)
        {

        }

        public void CloseAccount(int accountNumber)
        {

        }
    }

これらのアクションを実行する必要があることを知って、コードを記述する前に最初に行うことは、単体テストの記述を開始することです。

   [TestFixture]
    public class AccountServiceTests
    {
        [Test]
        public void DebitAccountTest()
        {

        }

        [Test]
        public void CreditAccountTest()
        {

        }

        [Test]
        public void CloseAccountTest()
        {

        }
    }

テストを作成して、何かを実行するために作成したコードを検証します。一連のものを繰り返し処理し、それぞれについて何かを変更する場合は、同じことを行うテストを作成し、実際に起こったことをアサートします。

他にも多くの方法があります。具体的には、動作駆動型開発 (BDD) などがありますが、これはより複雑であり、ユニット テストのスキルを開始するのに最適な場所ではありません。

したがって、この話の教訓は、懸念される可能性のあることは何でもテストし、サイズの小さい特定のものを単体テストでテストし続けることです。多くのテストは良いことです。

ビジネス ロジックをユーザー インターフェイス レイヤーの外に置いて、簡単にテストを記述できるようにします。

どちらも Visual Studio に簡単に統合できるので、TestDriven.NetまたはReSharperをお勧めします。

于 2008-09-15T13:23:50.050 に答える
1

理想的には、クラスを作成する際に単体テストを行ったはずです。これは、テスト駆動開発を使用する際に意図されている方法です。各ファンクション ポイントを実装するときにテストを追加し、エッジ ケースもテストで確実にカバーします。

後でテストを書くのはかなり面倒ですが、実行可能です。

あなたの立場で私がすることは次のとおりです。

  1. コア機能をテストする基本的な一連のテストを記述します。
  2. NCover を入手して、テストで実行してください。この時点で、テスト カバレッジはおそらく 50% 程度になります。
  3. 約 80% ~ 90% のカバレッジが得られるまで、エッジ ケースをカバーするテストを追加し続けます。

これにより、リグレッションに対する適切なバッファーとして機能する単体テストの適切な作業セットが得られるはずです。

このアプローチの唯一の問題は、この方法でテストできるようにコードを設計する必要があることです。早い段階でカップリングのミスを犯した場合、高いカバレッジを簡単に得ることはできません。

これが、コードを書く前にテストを書くことが本当に重要な理由です。疎結合のコードを書く必要があります。

于 2008-09-15T13:13:19.827 に答える
1

明らかに動作する (ボイラープレート) コードをテストしないでください。したがって、セッターとゲッターが単に「propertyvalue = value」および「return propertyvalue」である場合、それをテストしても意味がありません。

于 2008-09-15T13:13:45.643 に答える
1

get / set でさえ、実装方法によっては奇妙な結果になる可能性があるため、メソッドとして扱う必要があります。

これらの各テストでは、プロパティのパラメーターのセットを指定し、許容できるプロパティと許容できないプロパティの両方を定義して、呼び出しが期待どおりに返されるか失敗することを確認する必要があります。

また、SQL インジェクションの例として、セキュリティの問題を認識し、これらをテストする必要があります。

そうです、プロパティのテストについて心配する必要があります。

于 2008-09-15T13:14:07.063 に答える
1

アジャイル開発のコンテキストで単体テストを理解しているので、マイク、はい、ゲッターとセッターをテストする必要があります (公開されていると仮定します)。単体テストの全体的な概念は、この場合はクラスであるソフトウェア ユニットをブラック ボックスとしてテストすることです。ゲッターとセッターは外部から見えるため、認証と保存とともにテストする必要があります。

于 2008-09-15T13:08:05.330 に答える
1

Authenticate メソッドと Save メソッドがプロパティを使用する場合、テストは間接的にプロパティに触れます。プロパティがデータへのアクセスを提供するだけである限り、明示的なテストは必要ありません (100% のカバレッジを目指す場合を除きます)。

于 2008-09-15T13:08:14.283 に答える
1

私はあなたのゲッターとセッターをテストします。コードを書いている人によっては、getter/setter メソッドの意味を変える人もいます。getter メソッドの一部として、変数の初期化やその他の検証を見てきました。このようなことをテストするには、そのコードを明示的にカバーする単体テストが必要です。

于 2008-09-15T13:09:16.170 に答える
1

個人的には、「壊れる可能性のあるものは何でもテスト」し、単純なゲッター (またはより優れた自動プロパティ) は壊れません。単純な return ステートメントが失敗したことは一度もないため、それらをテストしたことはありません。ゲッターに計算やその他の形式のステートメントがある場合は、確実にテストを追加します。

個人的には、Moqをモック オブジェクト フレームワークとして使用し、オブジェクトが周囲のオブジェクトを適切に呼び出すことを確認します。

于 2008-09-15T13:09:25.560 に答える
1

クラスのすべてのメソッドの実行を UT でカバーし、メソッドの戻り値を確認する必要があります。これには、特にメンバー (プロパティ) が複雑なクラスであり、初期化中に大量のメモリ割り当てが必要な場合に、ゲッターとセッターが含まれます。たとえば、非常に大きな文字列(またはギリシャ記号を含むもの)でセッターを呼び出し、結果が正しいことを確認します(切り捨てられていない、エンコードが適切であるなど)

同様に適用される単純な整数の場合 - 整数の代わりに long を渡すとどうなりますか? それがあなたがUTを書く理由です:)

于 2008-09-15T13:10:03.873 に答える
1

クラスのテストでは、次のことを確認する必要があります。

  1. メソッドとプロパティが期待値を返す
  2. 無効な引数が指定された場合、適切な例外がスローされます
  3. 特定のメソッドが呼び出されたときに、クラスと他のオブジェクト間の相互作用が期待どおりに発生する

もちろん、ゲッターとセッターに特別なロジックがない場合は、Authenticate メソッドと Save メソッドのテストでそれらをカバーする必要がありますが、それ以外の場合は明示的なテストを記述する必要があります。

于 2008-09-15T13:10:22.970 に答える
1

プロパティの実際の設定はテストしません。私は、これらのプロパティが消費者によってどのように入力されるか、およびそれらがそれらに何を入力するかについてもっと心配します. どのようなテストでも、リスクとテストの時間/コストを比較検討する必要があります。

于 2008-09-15T13:11:04.760 に答える
1

可能な限り単体テストを使用して、「すべての重要なコード ブロック」をテストする必要があります。

プロパティが些細なもので、誰かがバグを導入する可能性が低い場合は、それらを単体テストしない方が安全です。

Authenticate() および Save() メソッドは、テストに適しているように見えます。

于 2008-09-15T13:11:22.687 に答える
0

価値のないコードを書くことは常に悪い考えです。提案されたテストはプロジェクトに価値を追加しないため(またはプロジェクトに非常に近い)。次に、実際に価値をもたらすコードを書くために費やすことができる貴重な時間を無駄にしています。

于 2008-09-15T20:04:54.283 に答える
0

単体テスト、または実際にはすべてのテストを作成するときは、テスト対象の境界条件を調べて、何をテストするかを決定します。たとえば、is_prime という関数があるとします。幸いなことに、それはその名前が意味することを行い、整数オブジェクトが素数かどうかを教えてくれます。このために、オブジェクトを使用していると仮定しています。ここで、既知の範囲のプライム オブジェクトと非プライム オブジェクトに対して有効な結果が発生したことを確認する必要があります。それがあなたの出発点です。

基本的に、関数、メソッド、プログラム、またはスクリプトで何が起こるべきかを調べてから、同じコードで絶対に起こるべきではないことを見てください。それがあなたのテストの基礎です。コードで何が起こるべきかについての知識が深まるにつれて、テストを変更する準備をしてください。

于 2008-09-15T15:20:28.583 に答える
0

壊れる可能性のあるものはすべてテストし、ばかげたテストは書きません。しかし、最も重要な信条は、壊れているとわかったものはすべてテストすることです。メソッドが異常に動作する場合は、失敗するデータ セットの概要を説明するテストを作成し、バグを修正してバーが緑色になるのを確認します。また、「境界」データ値 (null、0、MAX_INT、空のリストなど) もテストします。

于 2008-09-15T15:16:57.767 に答える
0

私がこれまでに経験してきた最善の経験則は、一見しただけでは正しく動作するかどうかを確認できないものはすべてテストすることです。それ以上のことをすると、言語/環境をテストすることになります。

于 2010-04-26T21:44:23.780 に答える
-3

C# について具体的に話すことはできませんが、単体テストを作成するときは、ユーザーが行わない入力であっても、すべての入力をテストします。そうすれば、自分の間違いを防ぐ方法がわかります。

于 2008-09-15T13:07:01.667 に答える