{"id":8223,"date":"2015-04-18T08:56:00","date_gmt":"2015-04-18T15:56:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudioalm\/2015\/04\/18\/smart-unit-tests-test-to-code-binding-test-case-management\/"},"modified":"2022-07-27T06:12:59","modified_gmt":"2022-07-27T14:12:59","slug":"smart-unit-tests-test-to-code-binding-test-case-management","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/smart-unit-tests-test-to-code-binding-test-case-management\/","title":{"rendered":"Smart Unit Tests &#8211; Test to Code Binding, Test Case Management"},"content":{"rendered":"<p><em>[Editor\u2019s note: &#8220;Smart Unit Tests&#8221; has been renamed to \u201c<strong>IntelliTest<\/strong>\u201d with effect from Visual Studio 2015 Release Candidate (RC).]<\/em><\/p>\n<p>In an <a href=\"http:\/\/blogs.msdn.com\/b\/visualstudioalm\/archive\/2014\/11\/19\/introducing-smart-unit-tests.aspx\">earlier post<\/a> we had mentioned how Smart Unit Tests can emit a suite of tests for a given code-under-test, and how it can manage this test suite as the code-under-test itself evolves. For any given method serving as the code-under-test, the emitted\u00a0test suite comprises of a &#8220;parameterized unit test&#8221; and one or more &#8220;generated unit tests&#8221;, and the\u00a0following\u00a0figure illustrates\u00a0the *Pex** custom attributes used to identify the ***test-to-code binding***, that in turn enables such management. These attributes are defined within the Microsoft.Pex.Framework namespace.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2015\/04\/1373.testToCodeBinding6.jpg\" alt=\"\" border=\"0\" \/><\/p>\n<p><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\">At compile time, these attributes are baked into the assembly as metadata for the types and methods to which they were applied. On subsequent invocations, Smart Unit Tests can reflect on the assembly and, with the help of this metadata, re-discover the test-to-code binding.<\/span><\/p>\n<p><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\">As you would have noticed, the generated unit tests are just traditional unit tests; indeed, they will show up in the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/hh270865.aspx\">Visual Studio Test Explorer<\/a> just like any other hand written test, although it is not expected that such generated unit tests will be edited by hand. Each generated unit test calls into the parameterized unit test which then calls into the code-under-test.<\/span><\/p>\n<p><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\">The programmatic separation between the generated unit tests and the parameterized unit test allows the parameterized unit test to serve as a single location where you can specify correctness properties about the code-under-test, that all of the generated unit tests can validate. In a future post we will discuss ways to express such correctness properties, but it is not a matter of concern for the test-to- code binding, the topic of this post. What does matter is that the generated unit tests and the parameterized unit test are placed into the same assembly.<\/span><\/span><\/p>\n<p><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\">The management of these generated unit tests involves the following:<\/span><\/span><\/p>\n<ul>\n<li><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><strong>Preventing the emission of duplicate tests<\/strong>: the code-under-test is always explored from scratch by the testing engine. Therefore it might generate tests that had already been generated before, and such tests should not be emitted.<\/span><\/span><\/li>\n<li><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><strong>Deleting tests that have become irrelevant<\/strong>: when the code-under-test changes, previously relevant tests might become irrelevant, and might need to be replaced with new tests.<\/span><\/span><\/span><\/li>\n<\/ul>\n<p><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\">Here is how it is done:<\/span><\/span><\/span><\/span><\/p>\n<p><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\">Given that the parameterized unit test and the generated unit tests are placed into the same assembly, the testing engine pre-processes any existing \u201cgenerated unit tests\u201d (emitted previously) by scanning the assembly for the test fixture (identified by the type having the <strong>PexClass <\/strong>annotation). Generated unit tests are recognized by the Test attribute (the <strong>TestMethod<\/strong>, and <strong>PexGeneratedBy<\/strong> annotations in this case). For each such unit test method, it fetches the source code, trims away all whitespaces and uses the resulting string as a \u201chash\u201d of the generated test. Once this is done, the testing engine has a dictionary of such hashes that it can consult to determine whether a newly generated test already exists. Duplicate tests are not emitted, and if a previously existing test case is not generated, it is deleted.<\/span><\/span><\/span><\/p>\n<p><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\"><span style=\"line-height: 107%;font-family: 'Calibri',sans-serif;font-size: 11pt\">Keeping a suite of unit tests in sync with a fast-evolving code base is a challenge. Manually adapting the code of a potentially large number of unit tests incurs significant costs. We hope such automatic management of the suite of generated unit tests helps in addressing this challenge. As ever, report any issues or overall feedback below, or through the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/zzszcehe.aspx\">Send a Smile feature<\/a> in Visual Studio.<\/span><\/span><\/span><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[Editor\u2019s note: &#8220;Smart Unit Tests&#8221; has been renamed to \u201cIntelliTest\u201d with effect from Visual Studio 2015 Release Candidate (RC).] In an earlier post we had mentioned how Smart Unit Tests can emit a suite of tests for a given code-under-test, and how it can manage this test suite as the code-under-test itself evolves. For any [&hellip;]<\/p>\n","protected":false},"author":765,"featured_media":45953,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[226,1,252],"tags":[],"class_list":["post-8223","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ci","category-devops","category-testing"],"acf":[],"blog_post_summary":"<p>[Editor\u2019s note: &#8220;Smart Unit Tests&#8221; has been renamed to \u201cIntelliTest\u201d with effect from Visual Studio 2015 Release Candidate (RC).] In an earlier post we had mentioned how Smart Unit Tests can emit a suite of tests for a given code-under-test, and how it can manage this test suite as the code-under-test itself evolves. For any [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/8223","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/765"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=8223"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/8223\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/45953"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=8223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=8223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=8223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}