{"id":1847,"date":"2014-08-01T00:00:00","date_gmt":"2014-08-01T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/a-tdd-journey-5-tests-vs-code-refactor-friendliness-test-parameterization\/"},"modified":"2026-03-06T11:04:24","modified_gmt":"2026-03-06T11:04:24","slug":"a-tdd-journey-5-tests-vs-code-refactor-friendliness-test-parameterization","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/a-tdd-journey-5-tests-vs-code-refactor-friendliness-test-parameterization\/","title":{"rendered":"TDD Practices: Test Parameterization &#038; Refactor-Friendly Tests in C#"},"content":{"rendered":"<div id=\"pretty\">\n<p>In TDD, test code is arguably more valuable than production code &#8211; because you can recreate production code from well-written tests, but you cannot recreate tests from production code. This installment covers three practices that protect that investment: ensuring tests remain valid when you refactor production code (refactor-friendliness), using test parameterization to eliminate duplicate test logic without adding complexity, and recognizing when tests pass for the wrong reason. These techniques help maintain a clean, trustworthy test suite as your codebase evolves.<\/p>\n<ul class=\"list--tight\">\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/.net-framework\/a-tdd-journey-1-trials-and-tribulations\/\">Part 1: Trials and Tribulations of TDD<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/.net-framework\/a-tdd-journey-2--naming-tests-mocking-frameworks-dependency-injection\/\">Part 2: Naming Tests; Mocking Frameworks; Dependency Injection<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/.net-framework\/a-tdd-journey-3--mocks-vs.-stubs-test-frameworks-assertions-resharper-accelerators\/\">Part 3: Mocks vs. Stubs; Test Frameworks; Assertions; ReSharper Accelerators<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/.net-framework\/a-tdd-journey-4-tests-as-documentation-false-positive-results-component-isolation\/\">Part 4: Tests as Documentation; False Positive Results; Component Isolation<\/a><\/li>\n<li><b>Part 5: Tests vs. Code; Refactor Friendliness; Test Parameterization<\/b><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/net-framework\/a-tdd-journey-6-mini-factory-pattern-dont-care-terms\/\">Part 6: Mini-Factory Pattern; Don&#8217;t Care Terms<\/a><\/li>\n<\/ul>\n<p>This is part 5 of our exploration into practicing hands-on TDD. Unlike most of my multi-part series, it is <i>not<\/i> advisable to join this one in the middle. So if you are arriving fresh, please go back and review part 1 for an overview of TDD and subsequent parts that both built out our tests &amp; code and introduced ancillary concepts and techniques crucial to the TDD approach.<\/p>\n<p>Here are the tests we have developed so far. This list of behaviors documents the rather simple operations our class under test knows how to handle at this point in development:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">WidgetActivatorTest:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WidgetActivator_constructor_accepts_an_IWidgetLoader\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Execute_delegates_to_IWidgetLoader_to_load_widget_details\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WidgetActivator_constructor_accepts_an_IWidgetPublisher\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Execute_delegates_to_IWidgetPublisher_to_publish_widget\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Execute_returns_false_if_no_details_to_load\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Execute_returns_true_if_details_are_loaded\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Execute_returns_false_if_publishing_failed\n<\/pre>\n<div class=\"theory\">\n<h2><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img2C.gif\" alt=\"2019-img2C.gif\" \/>Importance of Tests vs. Code<\/h2>\n<p>Let&#8217;s start off this installment with a question to consider: what is more important in TDD-test code or production code? Consider for a moment before reading further. Then write down your answer so you cannot hedge :-).<\/p>\n<p>I predict you will scoff at the question: <i>obviously<\/i> your production code is more valuable because <i>that<\/i> is what you sell or deliver or install. Your customers do not pay you for your test code. Indeed, your customers never see your test code. But is it really so obvious? You learned in part 4 that everything you need to know about your class under test is embodied in a simple list of the names of the tests.<\/p>\n<p>From <i>just<\/i> that information you can deduce we are testing a <code>WidgetActivator<\/code> ; it has an Execute method; Execute returns a Boolean status; the <code>WidgetActivator<\/code> uses an <code>WidgetLoader<\/code> and <code>IWidgetPublisher<\/code> both of which have a method that also returns a Boolean status; and the return value of Execute is a conjunction of the return values of its components. And that is just from the test <i>names<\/i>. Now if you had the full bodies of the test methods you can be more precise and more detailed. I submit, in fact, that if you lost your production code you could recreate it reliably and accurately from the tests!\u00a0 How about the other way? If you lost your tests, what would happen? For a brief moment in time you have working production code. But if you proceed with new development, bug fixes, patches, etc., your code evolves and you do <i>not<\/i> have the safety net of your TDD-developed unit tests to guarantee the stability of your code. You could recreate <i>some<\/i> set of unit tests, of course, but it would be rather improbable that you could recreate your complete set of tests to provide full coverage of your code. So let me ask again: which is more important-test code or production code?<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img32.gif\" alt=\"2019-img32.gif\" \/><\/figure>\n<\/div>\n<p class=\"FailingParagraph\">TEST: The last test covered when publishing fails; let&#8217;s now put in a test for when publishing succeeds&#8230;<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">\t\t[Test]\npublic\u00a0void\u00a0Execute_returns_true_if_publishing_succeeded()\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Setup(x\u00a0=&gt;\u00a0x.Publish())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Returns(()\u00a0=&gt;\u00a0true);\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0var\u00a0result\u00a0=\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0Assert.That(result,\u00a0Is.True);\n}\n<\/pre>\n<p class=\"PassingParagraph\">CODE: That test fails for the same reason the <code>WidgetLoader<\/code> test failed when the load was successful-we did not isolate the <code>WidgetLoader<\/code> in the test. Here it is just the reverse: we need to isolate the <code>IWidgetPublisher<\/code> by forcing the <code>WidgetLoader<\/code> to always return true, then this test passes.<\/p>\n<pre class=\"lang:tsql theme:ssms2012\"> [Test]\npublic\u00a0void\u00a0Execute_returns_true_if_publishing_succeeded()\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Setup(x\u00a0=&gt;\u00a0x.Publish())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Returns(()\u00a0=&gt;\u00a0true);\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0true\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0); \u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0var\u00a0result\u00a0=\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0Assert.That(result,\u00a0Is.True);\n}\n<\/pre>\n<p>But wait a minute; this test is a sham! It purports to validate the behavior that IF publishing succeeds THEN Execute succeeds. Period. It does <i>not<\/i> say that if publishing succeeds <i>when loading succeeds<\/i> then Execute succeeds. Yet that is exactly what we just coded. So this reveals a weakness in the behavior specification, i.e. the test name. It might be better to state<br \/><code>Execute_reflects_the_publishing_result_if_publishing_succeeded<\/code>,<br \/>suggesting there are other factors that are also reflected in the result of Execute. But that is a bit too wibbly-wobbly. I prefer something like &#8230;<br \/><code>Execute_returns_true_when_publishing_succeeds_after_loading_succeeds<\/code>.<br \/>Similarly we will be best served by renaming the related tests:<\/p>\n<p><code>Execute_returns_true_if_publishing_succeeded =&gt;<br \/>\nExecute_returns_true_when_publishing_succeeds_after_loading_succeeds<\/code> <code>Execute_returns_false_if_publishing_failed =&gt;<br \/>\nExecute_returns_false_when_publishing_fails_after_loading_succeeds<\/code> <code>Execute_returns_true_if_details_are_loaded =&gt;<br \/>\nExecute_returns_true_when_loading_succeeds_and_then_publishing_succeeds<\/code> <code>Execute_returns_false_if_no_details_to_load =&gt;<br \/>\nExecute_returns_false_when_loading_fails_and_then_publishing_succeeds<\/code><\/p>\n<p>These are much clearer because they are explicitly showing which component we are isolating while holding the other component constant.<\/p>\n<div class=\"theory\">\n<h2><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img2C.gif\" alt=\"2019-img2C.gif\" \/>Reprise: Beware Passing Tests<\/h2>\n<p>A key tenet of the previous article in this series bears repeating:<\/p>\n<div>\n<div>\n<p>Watch out for tests that pass for the wrong reason!<\/p>\n<\/div>\n<\/div>\n<p>The penultimate test we wrote was the opposite of our latest test:<br \/><code>Execute_returns_false_if_publishing_failed<\/code>. And in the last article you saw how that test passed only coincidentally. We needed to fix the production code to make it pass for the right reason. But let&#8217;s take one more look at that test <i>now with its new name<\/i>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">public\u00a0void\u00a0Execute_returns_false_when_publishing_fails_after_loading_succeeds()\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Setup(x\u00a0=&gt;\u00a0x.Publish())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Returns(()\u00a0=&gt;\u00a0false);\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0var\u00a0result\u00a0=\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0Assert.That(result,\u00a0Is.False);\n}\n<\/pre>\n<p>Do you see that this test <i>still<\/i> passes for the wrong reason (albeit a different wrong reason)? Here the test name points us to the culprit. This time, it is the test itself that needs correcting, with the very same fix we just used in the latest test: we must take the <code>WidgetLoader<\/code> out of the equation: this test will pass regardless of what the <code>mockWidgetPublisher<\/code> does because the <code>stubWidgetLoader<\/code> invokes its default behavior, returning false. We need to make loading succeed-as the test name now says-so that the results are meaningful:<\/p>\n<pre class=\"lang:tsql theme:ssms2012 mark:7,8,9\">public\u00a0void\u00a0Execute_returns_false_when_publishing_fails_after_loading_succeeds()\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Setup(x\u00a0=&gt;\u00a0x.Publish())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Returns(()\u00a0=&gt;\u00a0false);\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0true\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0var\u00a0result\u00a0=\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0Assert.That(result,\u00a0Is.False);\n}\n\n<\/pre>\n<figure><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img32.gif\" alt=\"2019-img32.gif\" \/><\/figure>\n<\/div>\n<p>Now that we have the loader and the publisher nominally acting reasonably, let&#8217;s consider what to do next: of course you do not have any domain knowledge about this <code>WidgetActivator<\/code> and its components just from the class names, but let&#8217;s agree it is reasonable that if we fail to load our widget there is no point in publishing it.<\/p>\n<p class=\"FailingParagraph\">TEST: In this test we force the loader to report failure, then we check that the publisher is never used. This test fails because, as written, the <code>WidgetActivator<\/code> always invokes both the loader and the publisher.<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">\t\t[Test]\npublic\u00a0void\u00a0Execute_only_publishes_if_loading_succeeds()\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0false);\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher.Verify(x\u00a0=&gt;\u00a0x.Publish(),\u00a0Times.Never);\n}\n<\/pre>\n<p class=\"PassingParagraph\">CODE: Let&#8217;s add a conditional to only invoke the publisher when appropriate. I have also renamed the local variable from result to success to make it more meaningful in this context.<\/p>\n<pre class=\"lang:tsql theme:ssms2012 mark:5,6,8\">public\u00a0bool\u00a0Execute()\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0success\u00a0=\u00a0_widgetLoader.Load();\n\u00a0\u00a0\u00a0\u00a0if\u00a0(success)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0success\u00a0&amp;=\u00a0_widgetPublisher.Publish();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0return\u00a0success;\n}\n<\/pre>\n<p class=\"PassingParagraph\">CODE: That made this new test pass, but it made one of our first tests fail,<br \/><code>Execute_delegates_to_IWidgetPublisher_to_publish_widget.<\/code><br \/>The reason is clear: in this barebones test we gave the loader and publisher no mocking behaviors so method calls basically return null or false, as appropriate. The code change we just put in inhibits the call to the publisher, hence the test failure. Rather than fix this test, though, I am going to be a bit more draconian and just delete it.<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">[Test]\n\u00a0public\u00a0void\u00a0Execute_delegates_to_IWidgetPublisher_to_publish_widget()\n\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\u00a0\u00a0\u00a0\u00a0\u00a0activator.Execute();\n\u00a0\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher.Verify(x\u00a0=&gt;\u00a0x.Publish(),\u00a0Times.Once());\n\u00a0}\n<\/pre>\n<p>Why delete it?<\/p>\n<ol>\n<li>This test is rather na\u00efve: implicitly it is saying that we are using the <code>IWidgetPublisher<\/code> <i>in all cases<\/i>, but the last test just made that assumption invalid.<\/li>\n<li>\u00a0\u00a0\u00a0 This test is now redundant, covered by the other <code>IWidgetPublisher<\/code> tests we have written after this one. Clearly, if we are testing whether publishing failed or publishing succeeded, then we are making use of the <code>IWidgetPublisher<\/code> .<\/li>\n<li>This test is &#8220;non-refactor-friendly&#8221;.<\/li>\n<\/ol>\n<p>For the same reasons I am also going to delete the very first test,<br \/><code>\u00a0 Execute_delegates_to_IWidgetLoader_to_load_widget_details<\/code>.<br \/>I also do not see a great need for our very elementary tests,<br \/><code>\u00a0\u00a0 WidgetActivator_constructor_accepts_an_IWidgetLoader<br \/>\n<\/code>\u00a0and <code><br \/>\nWidgetActivator_constructor_accepts_an_IWidgetPublisher<\/code><br \/>so I will delete those now as well.<\/p>\n<div class=\"theory\">\n<h2><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img2C.gif\" alt=\"2019-img2C.gif\" \/>Refactor-Friendly Tests<\/h2>\n<p>A bit of an explanation: <i>Refactoring<\/i>, the process of restructuring code without changing its behavior, is an integral part of TDD. Indeed, almost synonymous with TDD is the term &#8220;red-green-refactoring&#8221;, introduced in part 1 of this series, and originally espoused by <a href=\"http:\/\/www.jamesshore.com\/Blog\/Red-Green-Refactor.html\">James Shore<\/a>. We have, in fact been following this process, which is to say, write a bit of a failing test (the test runner reports a failure, usually in <i>red<\/i>); write a bit of production code to make the test pass (<i>green<\/i>), then reflect upon the code, tidy it up, improve it, consolidate it (<i>refactor<\/i>).\u00a0 \u00a0Those of us in the .NET world are terribly spoiled with the refactoring power of ReSharper or CodeRush. (I understand IntelliJ Idea is as good in the Java world though I have not tried it.) These tools lets you move classes around, extract members out of classes, generate interfaces, and much more.<\/p>\n<p>But when we have a test <code>Execute_delegates_to_IWidgetPublisher_to_publish_widget<\/code> that specifically refers to the interface <code>IWidgetPublisher<\/code> <i>in its name<\/i>, this would not be noticed by ReSharper or its kin and thus if you chose to rename <code>IWidgetPublisher<\/code> to say, <code>IWidgetGluepot<\/code>, this test would essentially be an orphan, mentioning an interface that no longer exists. In short, explicitly embedding the name of a class, interface, etc., within a test name is non-refactor-friendly.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img32.gif\" alt=\"2019-img32.gif\" \/><\/figure>\n<\/div>\n<p>Let&#8217;s look again at the latest test, <code>Execute_only_publishes_if_loading_succeeds<\/code>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">[Test]\npublic\u00a0void\u00a0Execute_only_publishes_if_loading_succeeds()\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0false);\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher.Verify(x\u00a0=&gt;\u00a0x.Publish(),\u00a0Times.Never);\n}\n<\/pre>\n<p>Does the <i>body<\/i> of this test fulfill the expectation of the <i>name<\/i> of the test? The answer is &#8220;No.&#8221; Can you spot why? The name of the test is actually making <i>two<\/i> claims: publish if loading succeeds <i>and<\/i> do <i>not<\/i> publish if loading fails.<\/p>\n<div class=\"theory\">\n<h2><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img2C.gif\" alt=\"2019-img2C.gif\" \/>\u00a0Parameterized Test Cases<\/h2>\n<p>Here we are going to introduce a new construct from the NUnit framework, the <code>TestCase <\/code>attribute. Using <code>TestCase<\/code> instead of <code>Test<\/code> lets you specify parameters to the test. This is quite useful when you want to write two (or more than two) nearly identical tests. \u00a0In this instance we want the Load to succeed or the load to fail. So we introduce a parameter value in the <code>TestCase<\/code> attribute. We also add a parameter to the method signature that maps to that parameter value. Finally, we use that parameter as the value for the Load method to return:<\/p>\n<pre class=\"lang:tsql theme:ssms2012 mark:1,2,4\">[TestCase(false)]\npublic\u00a0void\u00a0Execute_only_publishes_if_loading_succeeds(bool\u00a0loaderSuccess)\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0loaderSuccess);\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher.Verify(x\u00a0=&gt;\u00a0x.Publish(),\u00a0Times.Never);\n}\n<\/pre>\n<p>With that in place, we can now add the second, very similar test case with just an attribute addition:<\/p>\n<pre class=\"lang:tsql theme:ssms2012 mark:1\">[TestCase(true)]\n[TestCase(false)]\npublic\u00a0void\u00a0Execute_only_publishes_if_loading_succeeds(bool\u00a0loaderSuccess)\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0loaderSuccess);\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher.Verify(x\u00a0=&gt;\u00a0x.Publish(),\u00a0Times.Never);\n}\n<\/pre>\n<p>In your unit test runner of choice, run all the tests and see what happens. Here is what ReSharper&#8217;s unit test runner reveals. Notice how these two new tests are now grouped together under the one test name. But more importantly, notice that the new test fails&#8230;<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img28.gif\" alt=\"2019-img28.gif\" \/><\/figure>\n<p>&#8230;because while we configured the test to take different <i>inputs<\/i> we did not tell it how that should affect the <i>output<\/i>. \u00a0One small change will clear up that error; making the output depend on that input parameter.<\/p>\n<pre class=\"lang:tsql theme:ssms2012 mark:14\">[TestCase(true)]\n[TestCase(false)]\npublic\u00a0void\u00a0Execute_only_publishes_if_loading_succeeds(bool\u00a0loaderSuccess)\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(\n    x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0loaderSuccess\n    );\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher.Verify(x\u00a0=&gt;\u00a0x.Publish(),\n    loaderSuccess ? Times.Once() : Times.Never());\n}\n<\/pre>\n<p>Notice how straightforward it is to understand this test. If you give this to someone who has never seen it, the thought process to understand it might go something like this:<\/p>\n<p>The test name states that it should check that publishing depends on whether loading succeeds or not. There are thus two test cases defined; one that forces the load to succeed and one that forces it to fail. If it succeeds, then the Verify statement wants Publish to be hit once; if it fails, Publish should not be hit at all.<\/p>\n<p>Note that I have introduced only a very small code complication to handle the two test cases-the ternary conditional in the <code>Verify<\/code> statement. If I needed anything more complicated than that, I would generally use two separate test cases, because making test code more complex just to have a few less lines of test code is a false economy and a bad practice. Tests should be as simple as possible to be easily understood by you or others. You could be even more stringent, though, not allowing <i>any<\/i> additional code complexity other than introducing parameters with <code>TestCase()<\/code>. You could rewrite the test to meet this tighter constraint by adding a second parameter. Because Times.Once() is a method, though, we cannot pass that in as a value; the values to <code>TestCase<\/code> must be compile-time constants. But <code>Once<\/code> just means 1 and <code>Never<\/code> just means 0. So this is completely equivalent to the last version-with <i>no<\/i> additional code complexity.<\/p>\n<pre class=\"lang:tsql theme:ssms2012 mark:1,2,3,13\">[TestCase(true,\u00a01)]\n[TestCase(false,\u00a00)]\npublic\u00a0void\u00a0Execute_only_publishes_if_loading_succeeds(bool\u00a0loaderSuccess,\u00a0int\u00a0callCount)\n{\n\u00a0\u00a0\u00a0\u00a0var\u00a0stubWidgetLoader\u00a0=\u00a0Mock.Of&lt;IWidgetLoader&gt;(\n    x\u00a0=&gt;\u00a0x.Load()\u00a0==\u00a0loaderSuccess\n    );\n\u00a0\u00a0\u00a0\u00a0var\u00a0mockWidgetPublisher\u00a0=\u00a0new\u00a0Mock&lt;IWidgetPublisher&gt;();\n\u00a0\u00a0\u00a0\u00a0var\u00a0activator\u00a0=\u00a0new\u00a0WidgetActivator(stubWidgetLoader,\u00a0mockWidgetPublisher.Object);\n\n\u00a0\u00a0\u00a0\u00a0activator.Execute();\n\n\u00a0\u00a0\u00a0\u00a0mockWidgetPublisher.Verify(x\u00a0=&gt;\u00a0x.Publish(),\u00a0Times.Exactly(callCount));\n}\n<\/pre>\n<figure><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2019-img32.gif\" alt=\"2019-img32.gif\" \/><\/figure>\n<\/div>\n<p>Test case parameterization is a powerful mechanism for avoiding code duplication with no additional code complexity. The above test allowed for only two possible inputs, but imagine if you needed to test that a set of various strings were all recognized as a date, including perhaps: 1\/3\/2014, 1\/3\/14, 01\/03\/14, 1-3-2014, 2014-01-03, and others. Rather than repeat essentially the same test with just a different constant, use a set of <code>TestCase<\/code> attributes on top of a single test to save a lot of up-front coding and a lot of maintenance should things change down the road.<\/p>\n<p><strong>Also in the series:<\/strong><br \/>Part 1: <a href=\"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/a-tdd-journey-1-trials-and-tribulations\/\" target=\"_blank\" rel=\"noopener\">TDD Fundamentals<\/a><br \/>Part 3: <a href=\"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/a-tdd-journey-3-mocks-vs-stubs-test-frameworks-assertions-resharper-accelerators\/\" target=\"_blank\" rel=\"noopener\">Mocks vs stubs<\/a><br \/>Part 6: <a href=\"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/a-tdd-journey-6-mini-factory-pattern-dont-care-terms\/\" target=\"_blank\" rel=\"noopener\">Mini-factory pattern<\/a><\/p>\n<\/div>\n\n\n<section id=\"my-first-block-block_da517328379b3747549081d66cf89e2d\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Save 35% on Redgate&#8217;s .NET Developer Bundle<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            Fantastic value on our .NET development tools for performance optimization and debugging.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/products\/dotnet-developer-bundle\/\" class=\"btn btn--secondary btn--lg\" aria-label=\"Learn more: Save 35% on Redgate&#039;s .NET Developer Bundle\">Learn more<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>FAQs: A TDD Journey 5- Tests vs. Code; Refactor Friendliness; Test Parameterization<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. What is test parameterization in TDD?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Test parameterization lets you run the same test logic with different input values, eliminating duplicate test methods. In NUnit, you use the [TestCase] attribute to supply different argument combinations to a single test method. This keeps your test suite DRY (Don\u2019t Repeat Yourself) while covering multiple scenarios. Each parameterized case runs as an independent test, so failures identify exactly which input combination broke.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. How do you write refactor-friendly unit tests?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Write tests that validate behaviors (what the code does) rather than implementation details (how it does it). Avoid testing private methods directly, avoid asserting on specific method call counts unless the count is the behavior you care about, and isolate your assertions so each test validates one behavior. When you refactor production code, refactor-friendly tests should continue to pass without modification if the behavior hasn\u2019t changed.<\/p>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Advanced TDD techniques in C#: test parameterization to reduce duplication, writing refactor-friendly tests, and understanding why test code can be more valuable than production code.&hellip;<\/p>\n","protected":false},"author":221868,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4229],"coauthors":[6802],"class_list":["post-1847","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-net-framework"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1847","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221868"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1847"}],"version-history":[{"count":7,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1847\/revisions"}],"predecessor-version":[{"id":108987,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1847\/revisions\/108987"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1847"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1847"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1847"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1847"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}