C# Unit Testing: Why must the expected result be included in the test name?

If the expected result of the method being tested exists in the official documentation of the method, then indicating the expected result in the test names would be redundant. In fact, if the purpose is to document the method, then the documentation should be written in the method's XML documentation which would provide Intellisense info and more.

Why must anything besides the method being tested really be included in a test name?

-------------Problems Reply------------

It's a matter of convention and development practice. If you're implementing using TDD, documenting the expected result in the test name keeps you focused on your goal. There is also no XML docs to specify the expected result on as you haven't implemented the class yet. (You're writing the test first.) The additional benefit here is that documenting the expected result in the test means that you can execute the specification (aka test) and verify that it is correct. You can't execute XML docs. :) (You do have to make sure that test name and test code match though. This is easier than making sure test code and XML docs in another file match.)

Beyond that, there are tools that will extract class/method names and generate specification documents for you in HTML. This allows you to easily generate reports that can be reviewed by all stakeholders. You would want to do this for high-level tests/specs, such as "When a 10 percent single-item discount code is applied during checkout, the most expensive item in the shopping cart is discounted by 10 percent." This allows stakeholders to verify (because the specs are executing/passing) that the system implements certain business-relevant features.

Well it doesn't, but if you say have 10+ tests trying different scenarios against the same method, not having it as descriptive as possible gets to be a real hassle when looking at them.

In the test list editor, you get the name of the test and that's all. On my project we currently have 600+ tests, so knowing which method does what can be really important when you are running them, and you want to try a certain scenario.

I always thought if something doesnt suit ur needs dont use it/mend it to fit your needs. The only logical explanation i can think of is that after you run the test methods you can export the pass/fail record and give it to the managers so that they can have a smile on their face cuz I dont know why they are so serious :).. Jokes apart.. another reason why BDD is slowly but surely gaining momentum.

Really you can name your test methods whatever you want, they're just methods. Pick a naming convention that works for you/your team.

However, most test runners do not display the XML documentation, only the method name. If the method name is sufficiently descriptive, you do not need to examine the test code to get an idea of what happened (or didn't happen) to cause the test to fail.

The test name should include the method being tested and the variant being tested. Typically you should have a lot more tests than methods being tested. You want at least a test for all boundary conditions, different branches, etc.

MyMethod_Zero()
MyMethod_MinValue()
MyMethod_MaxValue()
MyMethod_SomeBranchTest()

etc.

Because PoppingEmptyStackThrowsInvalidOperationException() is far easier to understand when looking at a test runner than StackPopTest_1()

I don't know and I don't like the most common naming conventions. I find them hard to read and understand. Based on few other naming conventions (which I cannot tell which one now) I developed my own, here it is:

Let's say I have the following class to test:

public class ColorParser {
public static bool TryParseHex(string value, out Color color) {
// Code to parse the hex color value.
}
}

My unit tests for this particular method look like the following:

public class ColorParserTests
{
public class TryParseHexTests
{
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void TestNullValue()
{
Color color = Color.Empty;
ColorParser.TryParseHex(null, out color);
}

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void TestEmptyValue()
{
Color color = Color.Empty;
ColorParser.TryParseHex(string.Empty, out color);
}

[TestMethod]
public void TestInvalidValues()
{
string[] invalidValues = new string[]
{
"#",
"FF",
"#FF",
"#FFAA",
"asdf"
};
foreach (var invalidValue in invalidValues)
{
Color color = Color.Empty;
bool result = ColorParser.TryParseHex(invalidValue, out color);
Assert.IsFalse(result, string.Format("Value '{0}' must not pass the test!", invalidValue));
}
}

[TestMethod]
public void TestValidValues()
{
// Spaces are intended and a part of the test!
Dictionary<string, Color> validValues = new Dictionary<string, Color>()
{
{" #000000", Color.FromArgb(0,0,0)},
{" #010203 ", Color.FromArgb(1,2,3)},
{"#00FFFF", Color.FromArgb(0,255,255)},
{"#FF00FFFF", Color.FromArgb(255,0,255,255)},
};
foreach (var validValue in validValues)
{
Color color = Color.Empty;
bool result = ColorParser.TryParseHex(validValue.Key, out color);
Assert.IsTrue(result, string.Format("Value '{0}' must pass the test!", validValue.Key));
Assert.AreEqual(validValue.Value, color, "Parsed color must be the same.");
}
}
}
}

The idea behind this is that the particualr tests are groupped (in classes) which allows me to test them separately. There is no need to repeat the method name being tested each time. The test method begins with a verb like a method name should and and it just contains a short information about what exacly is being tested. Everything else is inside the test.

This way I very quickly know what I'm testing and the results should be defined inside the tests themselves beacause what I'm testing is the behaviour for some values that either are correct or incorrect.

Nulls and Emptys and other special cases that throw exceptions deserve they own tests.

You could broke the tests up and write more tests like TestValuesWithSpaces or TestNegativeDeposit or TestUserNameWithInvalidCharacters etc. It always depends how much to test there is and how precise you want to do it. In this case I thought it's sufficient. Anyway I think this is very descriptive.

Category:c# Views:0 Time:2010-11-23

Related post

  • Is it appropriate to hardcode expected results when unit testing date and time formatting? 2012-02-07

    I like to keep my unit tests pretty simple and easy to follow. I often hardcode the expected results of a test in order to avoid repeating the code that I am testing. In addition, I often use data-driven tests. For example, if I am testing the format

  • Xml string representation of expected result for Junit test 2010-11-02

    I'm writing a Junit test in which the expected result is a XML string. What's the best way represent the expected string? Right now I have it as a stringBuilder and I do the following. I want to assert that the actual and expected are same. What woul

  • Unit Test inconsistent pass or fail result 2011-05-16

    One of my unit tests seems to randomly pass or fail when I run it. The only thing that makes sense to me for why this is happening is if the data in the database is getting into a different state each time the test is ran, but I use transactions to r

  • Best way to compare EXPECT result with our true records in Jasmine testing framework? 2012-01-16

    What are the ways to compare the expect results with our true records using Jasmine Testing Framework? One of the way is to use a static values within expect Parameters which is good for very basic values... But it has several limitations like it doe

  • The 'tap' method on String object doesn't return expected result 2009-08-26

    I ran in to an interesting problem while using the 'tap' method on objects of type 'String'. "abc".tap { |o| o = "xyz" } # this line returns "abc" instead of "xyz" The 'tap' method works on objects of other types. [].tap { |o| o << "xyz" } # th

  • Java exec() does not return expected result of pipes' connected commands 2010-01-18

    I'm calling command line programs connected by pipes. All this works on Linux for sure. My method: protected String execCommand(String command) throws IOException { String line = null; if (command.length() > 0) { Process child = Runtime.getRuntime

  • late static in PHP 5.3 doesn't produce expected result while inherit 2010-08-09

    I have a problem with static keyword due to inheritance in PHP 5.3. abstract class Object { protected static $_classDataSource = null; public static function getDataSource() { return static::$_classDataSource; } public static function setDataSource(

  • Why don't operations on double-precision values give expected results? 2010-10-08

    System.out.println(2.14656); 2.14656 System.out.println(2.14656%2); 0.14656000000000002 WTF? --------------Solutions------------- The do give the expected results. Your expectations are incorrect. When you type the double-precision literal 2.14656, w

  • Look Around does not deliver expected result with .net 2010-10-19

    I want to use a look-ahead regex for replacement with the System.Text.RegularExpression.Replace(...) method. Now I am wondering what's wrong. Look at this example code: string input = "stackoverflow"; string replacement = "#"; var pattern1 = "(?=[a-z

  • Firebird script not producing expected results 2010-11-05

    I am running the following Firebird SQL script but it is not producing the expected results after execution. I want to use it in my Delphi application, but am testing it in the EMS SQL Manager IDE first. After executing the script, all tables should

  • preg_match not returning expected results 2010-11-15

    I'm attempting to use regexp to parse a search string that from time to time may contain special syntax. The syntax im looking for is [special keyword : value] and i want each match put into an array. Keep in mind that the search string will contain

  • Linq to SQL query not returning expected results 2011-01-19

    Can anyone explain to me why these two are different functionally? The first returns null on my sample data, and the second returns the expected result. I put the + @"" part in to avoid calling replace on a null string. Code always returns null on my

  • Not getting expected results with RLIKE in MySQL 2011-01-20

    I'm using the next query: SELECT id,module,pk,label,value FROM traducciones WHERE module='paginas' AND label='slug' AND value RLIKE '(tests)(-\d+)?' The expected result will be only select: tests tests-1 tests-2 tests-N The problem is that I'm gettin

  • Query didn't gave me the expected result 2011-04-23

    ap table id tid code pid cl date 1 1 1002 17 DC 2011-04-05 16:14:37 2 1 1002 18 DC 2011-04-05 16:14:37 3 1 1002 19 DC 2011-04-05 16:14:37 4 2 1002 12 SC 2011-04-05 16:15:59 5 2 1002 9 SC 2011-04-05 16:15:59 6 2 1002 21 SC 2011-04-05 16:15:59 7 3 1003

  • retrieve Junit test expected result 2011-06-21

    I'm writing Junit test cases for a bunch of classes; each of them has a handful of method to test. The classes Im about to test look like the following. class A{ int getNth(int n); int getCount(); } class B{ int[] getAllNth(int n); int getMin(); } I

  • echo -n aWord | md5 not returning expected result 2011-07-01

    When I pass this line echo -n aWord | md5 directly in shell I get the expected result - same as PHP md5('aWord') - but when I call the code from a file I get a different string. Please help. --------------Solutions------------- If you get following m

  • HTML5 canvas putImageData seems to mess with pixels not getting expected results 2011-08-12

    I am trying to draw an isometric square with some custom code to build the pixel data up and then put it on a canvas with putImageData. But I'm not getting the expected results, after a quick look through the raw pixel data of the canvas it seems all

  • Distinct not returning expected result? 2011-08-29

    What wrong with this code (or my sanity for that matter :D ). The Distinct clause in the Select statement is NOT working. It's result set contains All rows for Each EmpID in ej. Please help!! Declare @SurveyID int; SET @SurveyID = 2; IF OBJECT_ID('te

  • Query not returning expected results 2011-09-02

    I'm trying to select all my areas and join the deals for those areas... this query is returning 0 results when I have verified that I have data to match what I'm expecting to get... does anyone see anything obviously wrong? SELECT deal.*, area.id AS

Copyright (C) dskims.com, All Rights Reserved.

processed in 0.134 (s). 11 q(s)