単体テストの命名のベストプラクティス[終了]


564

単体テストクラスとテストメソッドに名前を付けるためのベストプラクティスは何ですか?

これは以前にSOで議論されました、ユニットテストの一般的な命名規則は何ですか?

これが非常に優れたアプローチであるかどうかはわかりませんが、現在の私のテストプロジェクトでは、各プロダクションクラスとテストクラスの間で1対1のマッピングがProductありProductTestます。

私のテストクラスには、テストしているメソッドの名前、アンダースコア、そして状況と私が期待することを含むメソッドがありますSave_ShouldThrowExceptionWithNullName()



1
これは、あなたの質問に答えるが、価値は読み取りません。haacked.com/archive/2012/01/02/structuring-unit-tests.aspx
奪う

3
グーグルスタイルガイドは言う:test<MethodUnderTest>_<state>例えば、testPop_emptyStack google-styleguide.googlecode.com / svn / trunk / javaguide.html 5.2.3メソッド名。疑問がある場合は、Googleをフォローしてください。
Ciro Santilli郝海东冠状病六四事件法轮功

2
@CiroSantilli六四事件法轮功包卓轩そして、次の文は言う:「テストメソッドに名前を付ける正しい方法は一つない」。図を行きます。
user2418306 2016年

1
私はフィル・ハックの推薦を数年後も好む。
pimbrouwers 2018

回答:


524

私はロイオセロベの命名戦略が好きです。それは次のとおりです。

[UnitOfWork_StateUnderTest_ExpectedBehavior]

メソッド名と構造化された方法で必要なすべての情報があります。

作業単位は、単一のメソッド、クラスのように小さくすることも、複数のクラスのように大きくすることもできます。これは、このテストケースでテストされ、管理されるすべてのものを表す必要があります。

アセンブリの場合、私は典型的な.Testsエンディングを使用しますが、これは広く普及しており、クラス(で終わるTests)でも同じだと思います。

[NameOfTheClassUnderTestTests]

以前は、テストの代わりに接尾辞としてFixtureを使用していましたが、後者がより一般的であると考えて、命名戦略を変更しました。


228
私にとって、メソッド名をテストメソッドに入れるのは意味がありません。メソッドの名前を変更するとどうなりますか?テストの名前を変更するリファクタリングツールはありません。最終的には、テストメソッドの名前を手動で変更するか、誤った名前のテストを作成する可能性が高くなります。コメントのようなものです。コードにコメントを付けないよりもはるかに悪いです。
Piotr Perak、

80
@Peri、それはトレードオフだと思います。一方では、テスト名が古くなる可能性がありますが、他方では、テストがどのメソッドでテストされているかはわかりません。私は後者がはるかに頻繁に出てくることを見つけます。
ジョエル・マクベス

15
Periのコメントに追加するには-すべてのメソッドがいくつかのアクションを担当しUpdateManager.Update()ます。このことを念頭に持って、私は私のテストを呼び出すする傾向がありますWhenUpdating_State_BehaviourWhenUpdating_Behaviour_State。このようにして、メソッド名をテスト名に含めないようにしながら、クラスの特定のアクションをテストします。しかし、最も重要なことは、失敗したテストの名前が表示されたときに、どのビジネスロジックが失敗しているかの手掛かりを見つけなければならないということです
Ramunas

8
ResharperとIntelliJの両方がおそらくテストメソッドを見つけ、これらのツールを使用してリファクタリング/名前変更した場合は、その名前を変更することを提案します。また、メソッド名が記載されているコメントを調べて更新することも試みます。
Jeff Martin

62
多くの場合、適切なメソッド名は、メソッドが実行するアクションと同じです。メソッドの後にテストの名前を付けるか、メソッドが実行するアクションの名前を決める必要がある場合は、メソッドの名前を変更する必要あるかもしれません。(すべてのケースではありませんが)
Kaadzia '19

121

テスト対象のユニット(つまりクラス)の後にテストフィクスチャに名前を付けるときは、テスト「Should」命名基準に従います。

説明するには(C#とNUnitを使用):

[TestFixture]
public class BankAccountTests
{
  [Test]
  public void Should_Increase_Balance_When_Deposit_Is_Made()
  {
     var bankAccount = new BankAccount();
     bankAccount.Deposit(100);
     Assert.That(bankAccount.Balance, Is.EqualTo(100));
  }
}

なぜ「すべき」なのか?

テストの作成者に、「[ある状態にあるべき] [後で/前に/いつにすべきか] [アクションが行われるべきである」という文に沿ってテストに名前を付けることを強制していることがわかりました

はい、どこにでも「Should」と書くことは少し繰り返しが多くなりますが、前述したように、ライターは正しい方法で考える必要があります(初心者には良いかもしれません)。加えて、それは一般的に読みやすい英語のテスト名になります。

更新

Jimmy Bogardも「should」のファンであり、Shouldというユニットテストライブラリさえあることに気づきました。

アップデート(4年後...)

興味のある人のために、テストに名前を付ける私のアプローチは長年にわたって進化してきました。上記のShouldパターンの問題の1つは、どのメソッドがテスト中であるのかが一目でわかりにくいためです。OOPの場合、テスト対象のメソッドからテスト名を開始する方が理にかなっていると思います。適切に設計されたクラスの場合、これにより、テストメソッド名が読みやすくなります。現在、と同様の形式を使用しています<method>_Should<expected>_When<condition>。明らかにコンテキストによっては、Should / When動詞をより適切なものに置き換えたい場合があります。例: Deposit_ShouldIncreaseBalance_WhenGivenPositiveValue()


32
テストがうまくいくと仮定して、それが何をするかを説明する文を書いてくださいincreasesBalanceWhenDepositIsMade()
hotshot309

3
最近、同様の命名規則に言及している記事を見ました(ブックマークしたいと思います)。テストフィクスチャで並べ替えると、テストのリストが非常に読みやすくなるように設計されています。"BankAccount"のようなものが表示され、その下に(別の行に) "Should_Increase_Balance_When_Deposit_Is_Made" "Should_Decrease_Balance_When_Withdrawal_Is_Made"などが表示されます。TDDのすべてのような仕様に非常に似ています。
Simon Tewsi 2013年

記事を見つけました。Justin EtheredgeのCodeThinkedブログ、Moq 3によるモッキングの開始–パート1にあります。
Simon Tewsi 2013年

11
また、ShouldとWhenを使用しますが、その逆です。例:WhenCustomerDoesNotExist_ShouldThrowException()。私にとっては、これはいつすべきかよりもずっと理にかなっています(つまり、特定のシナリオでは、特定の期待される結果があるはずです)。これはAAA(アレンジ、アクト、アサート)にも適合します...アサートは最後にあります...最初ではありません;-)
bytedev

2
@Schneider:「すべき」=「推奨」、次にオプションと考えると、私は疑問に思います。たとえば、RFCは両方の違いをもたらします。テストに合格することが推奨または必須ですか?
Blackwizard 2017年

79

私はこの命名スタイルが好きです:

OrdersShouldBeCreated();
OrdersWithNoProductsShouldFail();

等々。テスター以外の人に問題が何であるかを明確にします。


63
-しかし、@ hotshot309、彼は.NET使用することができる.NET大文字表記
エース

2
@エース、私はあなたに完全に同意し、このコメントを投稿してから約1分後にこれに気づきました。間違いを見たときに削除したと誓ったが、どういうわけか、間違いではなかったと思う。申し訳ありません。
hotshot309 2012年

3
@CoffeeAddictは、識別子内のアンダースコアが<del>異常</ del>であるため、C#では実際に慣用的ではない
Sklivvz

2
私はまた、使用をshould好まwillないようにしたいOrdersWithNoProductsWillFail()
Calin

4
@Calin私の意見でWillは、使用は実際には適切ではなく、そうすることで、実際には、テストが失敗することは決してないという誤った方法で読者に伝えています... Will将来、発生しない可能性があることを表現するために使用する場合、間違って使用するのに対しShould、ここでは、何かが発生したい/したいが発生していない、または発生していないことを示しているため、より良い選択です。テストを実行すると、失敗/成功したかどうかが通知されるため、実際には事前に、それはそれに対する論理的な説明です、あなたは何ですか?なぜあなたは避けShouldますか?
Eyal Solnik、2016年

51

ケントベックは次のように提案しています。

  • 「ユニット」(プログラムのクラス)ごとに1つのテストフィクスチャ。テストフィクスチャはクラス自体です。テストフィクスチャ名は次のようになります。

    [name of your 'unit']Tests
    
  • テストケース(テストフィクスチャメソッド)の名前は次のとおりです。

    test[feature being tested]
    

たとえば、次のクラスがあるとします。

class Person {
    int calculateAge() { ... }

    // other methods and properties
}

テストフィクスチャは次のようになります。

class PersonTests {

    testAgeCalculationWithNoBirthDate() { ... }

    // or

    testCalculateAge() { ... }
}

4
より多くの人々がこれらのガイドラインに従うことを望みます。「ATest」、「BasicTest」、「ErrorTest」などの名前が付いていたため、20年以上前に名前を変更する必要がありました。
ウェッジ

85
クラスの接尾辞を考えると、「test」のメソッド接頭辞は冗長にならないのですか?
Gavin Miller

50
ケントがその本を書いたときのことを覚えておいてください。属性は発明されませんでした。したがって、メソッド名のTestという名前は、メソッドがテストであることをテストフレームワークに示しました。2002
Thomas Jespersen、

14
testCalculateAge ...これは、テストメソッドにとって意味のない名前です。「テスト」は冗長です(すべてのメソッドに「メソッド」プレフィックスを付けますか?)。名前の残りの部分には、テスト中の条件や期待されたものはありません。CalculateAgeはテスト中のメソッドですか?.....誰が知っているのか...
bytedev

1
この戦略を使用する場合は、予想される出力を指定するためのドキュメントが必要であることを付け加えておきます。'test'接頭辞についての補足として。一部の単体テストフレームワークでは、テストを認識するために特定のプレフィックスまたはサフィックスが必要です。抽象クラスの前に 'Abstract'を付けることは冗長であるとは見なされません(自己文書化であるため)。
siebz0r 2013

17

クラス名。テストフィクスチャ名については、「テスト」が多くのドメインのユビキタス言語で非常に一般的であることがわかりました。たとえば、エンジニアリングドメインStressTestでは、化粧品ドメインではですSkinTest。Kentに同意できないことに申し訳ありませんが、テストフィクスチャ(StressTestTest?)で "Test"を使用すると混乱します。

「ユニット」は、ドメインでも多く使用されます。例えばMeasurementUnitMeasurementUnitTest「Measurement」または「MeasurementUnit」のテストと呼ばれるクラスですか?

したがって、すべてのテストクラスに "Qa"プレフィックスを使用するのが好きです。例えばQaSkinTestQaMeasurementUnit。ドメインオブジェクトと混同されることはありません。接尾辞ではなく接頭辞を使用すると、すべてのテストフィクスチャが視覚的に共存します(テストプロジェクトに偽物やその他のサポートクラスがある場合に役立ちます)。

名前空間。私はC#で作業していて、テストクラスを、テストしているクラスと同じ名前空間に保持しています。個別のテスト名前空間を持つよりも便利です。もちろん、テストクラスは別のプロジェクトにあります。

メソッド名をテストします。私は自分のメソッドにWhenXXX_ExpectYYYという名前を付けたいです。それは前提条件を明確にし、自動化されたドキュメンテーション(la TestDox)に役立ちます。これはGoogleテストブログのアドバイスに似ていますが、前提条件と期待の分離が進んでいます。例えば:

WhenDivisorIsNonZero_ExpectDivisionResult
WhenDivisorIsZero_ExpectError
WhenInventoryIsBelowOrderQty_ExpectBackOrder
WhenInventoryIsAboveOrderQty_ExpectReducedInventory

あなたはテストメソッド名とテストフィクスチャ名について話しました。テストフィクスチャ名はプロダクションクラスにマップされます。テストのどこでプロダクションメソッド名を記述しますか?
The Light

12

私は「ギブン・ザーン・ザーン」という概念を使用しています。この短い記事http://cakebaker.42dh.com/2009/05/28/given-when-then/をご覧ください。記事ではBDDの観点からこの概念について説明していますが、TDDでも変更なしで使用できます。


Give-When-ThenはMethodName_Scenario_ExpectedBehaviorと同じですよね?!

1
ではない正確に。Given_When_Thenの詳細は次のとおりです。GivenAnEntity_WhenSomeActionHappens_ThatResultIsExpectedテストでは、実装ではなく動作をテストする意志を表現する必要があります
plog17

1
「与えられたとき」はしばしばガーキンと呼ばれます。そのDSLは、Cucumber、JBehave、およびBehatツールから出てきました。
bytedev 2016年

+1これは最良の方法です。メソッドがどのように結果を期待することから行うかを切り離すことは非常に強力であり、他のコメントで説明されている多くの問題を回避します。
Lee


7

最も重要なことの1つは、命名規則に一貫している(そして、チームの他のメンバーと同意する)ことだと思います。同じプロジェクトでさまざまな規則が使用されているのを何度も目にします。


7

私は最近、説明を最大化するために、テスト、クラス、およびプロジェクトを含むための次の規則を思いつきました。

名前空間のSettingsプロジェクトのクラスをテストしているとしましょうMyApp.Serialization

まず、MyApp.Serialization.Tests名前空間を使用してテストプロジェクトを作成します。

このプロジェクト内、そしてもちろん名前空間内にIfSettingsIfSettings.csとして保存された)というクラスを作成します。

SaveStrings()メソッドをテストしているとしましょう。->テストに名前を付けますCanSaveStrings()

このテストを実行すると、次の見出しが表示されます。

MyApp.Serialization.Tests.IfSettings.CanSaveStrings

これは、それが何をテストしているかを非常によく教えてくれると思います。

もちろん、英語では名詞「Tests」が動詞「tests」と同じであることは有用です。

テストに名前を付ける際の創造性に制限はないので、テストの全文見出しを取得できます。

通常、テスト名は動詞で始まる必要があります。

例は次のとおりです。

  • 検出(例DetectsInvalidUserInput
  • スロー(例ThrowsOnNotFound
  • 意志(例WillCloseTheDatabaseAfterTheTransaction

別のオプションは、「if」の代わりに「that」を使用することです。

後者は私にキーストロークを保存、テストされた動作が存在することを知らないので、私が何をしているかをより正確に説明しますが、存在するかどうかをテストしいます。

[ 編集 ]

上記の命名規則をもう少し長く使用した後、インターフェースを操作するときに、Ifプレフィックスが混乱する可能性があることがわかりました。テストクラスIfSerializer.csが[ファイルを開く]タブのISerializer.csインターフェースに非常に似ていることが偶然に起こります。これは、テスト、テスト対象のクラス、およびそのインターフェースの間で切り替えを行うときに非常に煩わしくなります。その結果、私は今、選ぶだろうそれを超える場合は接頭辞として。

さらに、次のように、テストメソッド名の単語を区切るために、「_」を使用します。

[Test] public void detects_invalid_User_Input()

これは読みやすいと思います。

[ 編集を終了 ]

テストが何であるかを理解するために費やしていたはずの多くの時間を節約できるので、テストに名前を付けることを非常に重要視することを検討しているので、これによりいくつかのアイデアが生まれることを願っています(たとえば、長期間の活動停止後にプロジェクトを再開した後) 。


2

VS + NUnitでは、通常、プロジェクトにフォルダーを作成して、機能テストをグループ化します。次に、単体テストフィクスチャクラスを作成し、テストする機能の種類に基づいて名前を付けます。[Test]メソッドは、次のように名前が付けられていますCan_add_user_to_domain

- MyUnitTestProject   
  + FTPServerTests <- Folder
   + UserManagerTests <- Test Fixture Class
     - Can_add_user_to_domain  <- Test methods
     - Can_delete_user_from_domain
     - Can_reset_password

2

テストを同じパッケージ内に、テスト対象のソースの並列ディレクトリに保持することで、多数の除外パターンを実行する必要がなく、コードを展開する準備ができたら、コードの肥大化を解消できます。

「JUnitポケットガイド」で説明されているベストプラクティスが個人的に気に入っています。JUnitの共著者が書いた本に勝るものはありません。


3
これが実際の目前の質問に答えているとは思わない-JUnit Pocket Guideを編集して参照してください。ありがとう!
Nate-Wilkins 14

0

クラスFooのテストケースの名前は、FooTestCaseまたはそれに類するもの(FooIntegrationTestCaseまたはFooAcceptanceTestCase)である必要があります。これはテストケースであるためです。テスト、テストケース、テストフィクスチャ、テストメソッドなどの標準的な命名規則については、http://xunitpatterns.com/を参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.