{"id":2811,"date":"2015-01-07T22:00:15","date_gmt":"2015-01-08T03:00:15","guid":{"rendered":"http:\/\/sqlity.net\/en\/?p=2811"},"modified":"2015-01-07T21:51:54","modified_gmt":"2015-01-08T02:51:54","slug":"testing-time","status":"publish","type":"post","link":"https:\/\/sqlity.net\/en\/2811\/testing-time\/","title":{"rendered":"Testing Time &#8211; Three Ways to Avoid Fragile Tests"},"content":{"rendered":"<div>\n<p>\nIn the <a href=\"http:\/\/sqlity.net\/en\/2787\/fragile-tests\/\">first post<\/a> of this series about fragile tests, we talked about how fragile tests can be a huge problem, undermining your unit testing efforts. In this second post of the series, I am looking at a special type of fragile tests: Tests that cover functionality that is dependent on the current time or date.\n<\/p>\n<div>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg\" alt=\"Testing Time\" title=\"Testing Time\" width=\"361\" height=\"450\" class=\"alignright size-full wp-image-2812\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg 361w, https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time-241x300.jpg 241w, https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time-120x150.jpg 120w\" sizes=\"auto, (max-width: 361px) 100vw, 361px\" \/><\/a>\n<\/div>\n<h3>Time Dependent Tests<\/h3>\n<p>\nA few weeks ago Jim asked a question on the tSQLt mailing list (<a href=\"https:\/\/groups.google.com\/forum\/#!forum\/tsqlt\" target=\"google\">tsql&#116;&#64;&#x67;&#x6f;&#x6f;&#x67;&#x6c;&#x65;group&#115;&#46;&#x63;&#x6f;&#x6d;<\/a>) about how to best test functionality that is dependent on one of the built-in time functions like <span class=\"tt\">SYSUTCDATETIME()<\/span>. I did, at the time, reply with an answer that got Jim unstuck, but I think it is worth going into a little more detail on this topic.\n<\/p>\n<p>\nJim was working on a procedure involved in application password resets. One of the business rules was to set an expiration time of <span class=\"tt\">DATEADD(MINUTE,15,SYSUTCDATETIME())<\/span> on any temporary password that was generated in this process.\n<\/p>\n<h3>Sporadic Test Failures<\/h3>\n<p>\nWhen you try to test this functionality, you should really test that the value written is exactly 15 minutes from now. However, test runtimes vary from execution to execution, making this impossible. Instead of testing the time exactly, you could allow for an uncertainty factor, for example 15 minutes from now plus\/minus 50 milliseconds. Such a test could look like this:\n<\/p>\n<div>\n[sql]\nCREATE PROCEDURE TimeDependentTests.[test example with 50ms fuzzy interval]\nAS<br \/>\nBEGIN<br \/>\n  EXEC tSQLt.FakeTable @TableName = 'Person.TempPasswords';<\/p>\n<p>  EXEC Person.CreateTemporaryPassword @PersonId = 2346;<\/p>\n<p>  DECLARE @ExpirationTimeDifference INT;<br \/>\n  SELECT @ExpirationTimeDifference = DATEDIFF(MILLISECOND,SYSUTCDATETIME(),ExpirationDTime)<br \/>\n    FROM Person.TempPasswords;<\/p>\n<p>  IF(    @ExpirationTimeDifference &lt; 15*60*1000-50<br \/>\n      OR @ExpirationTimeDifference &gt; 15*60*1000-50<br \/>\n      OR @ExpirationTimeDifference IS NULL<br \/>\n    )<br \/>\n  BEGIN<br \/>\n      EXEC tSQLt.Fail 'Wrong ExpirationTime set.';<br \/>\n  END;<\/p>\n<p>END;<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nHowever, for different reasons execution times of the same test can vary by a lot. This is particularly common on a development machine with a local SQL Server instance, but can happen on larger development or test servers too. Therefore, you might still see sporadic failures. You could now arbitrarily expand the interval, but I would not recommend going that way. The more uncertainty you allow, the more likely it is for an actual problem to slip through.\n<\/p>\n<h3>Possible Solutions<\/h3>\n<p>\nThere are several ways to handle time dependencies in your code (and tests). The three I most often use are:\n<\/p>\n<ol>\n<li>Parameterizing<\/li>\n<li>Wrapping<\/li>\n<li>Bracketing<\/li>\n<\/ol>\n<p>\nLet's look at them one by one.\n<\/p>\n<h3>Parameterizing<\/h3>\n<p>\nParameterizing time means, instead of calling a system function like <span class=\"tt\">SYSUTCDATETIME()<\/span> to get the current date and time within a procedure, require the current date and time to be passed in as a parameter. This has two big advantages. First, it makes testing a lot simpler, because now you can just pass in a known fixed timestamp in your tests:\n<\/p>\n<div>\n[sql]\nCREATE PROCEDURE TimeDependentTests.[test example with parameterized date and time]\nAS<br \/>\nBEGIN<br \/>\n  EXEC tSQLt.FakeTable @TableName = 'Person.TempPasswords';<\/p>\n<p>  EXEC Person.CreateTemporaryPassword<br \/>\n         @PersonId = 2346,<br \/>\n         @NowUTC = '2015-01-07T09:57:15.1234567';<\/p>\n<p>  SELECT ExpirationDTime<br \/>\n    INTO #Actual<br \/>\n    FROM Person.TempPasswords;<\/p>\n<p>  SELECT TOP(0) *<br \/>\n  INTO #Expected<br \/>\n  FROM #Actual;<\/p>\n<p>  INSERT INTO #Expected<br \/>\n  VALUES('2015-01-07T10:12:15.1234567');<\/p>\n<p>  EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';<br \/>\nEND;<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nBesides of not being fragile, the test is immediately more readable. Also, if it fails it gives clearer information about what went wrong. Additionally, you can be sure that a failure was actually caused by faulty code and not some one-time processing fluke.\n<\/p>\n<p>\nThe second advantage is not quite as obvious. I am often called to clients after they had a temporary problem, causing some important nightly\/weekly\/monthly process not to run. Now that process needs to be \"caught up\". However, the processing is based on the current date or time and cannot just be executed for say yesterday. Now clients are often contemplating an approach like this: Take server offline. Change server time. Rerun the process. Change server time back. Bring server back online.\n<\/p>\n<p>\nThis is an enormous effort. It also requires a downtime, which is often not an option. After that plan is ruled out, they start taking the code from the original process and write a new version that can handle this specific case. This is usually a high-pressure situation and causes all kinds of shortcuts to be taken. The thing that usually goes first is adequate testing. You probably can imagine what kind of disaster this leads to quite often.\n<\/p>\n<p>\nNow imagine how simple it would be to rerun the process for yesterday's date if you could just pass that date in as a parameter. Granted there might be other complications, but at least the time component would not be a hassle anymore.\n<\/p>\n<p>\nThe above applies to procedures and functions that are not part of a regular process too. In fact, I add that <span class=\"tt\">@NowUTC<\/span> parameter to all procedures and functions that are in any way dependent on the current time.\n<\/p>\n<h3>Wrapping<\/h3>\n<p>\nSometimes you cannot use the \"parameterizing\" pattern and you have to get the current date or time in your code directly. For example, if you use parameterization, you might want to make that parameter optional. Or, you might want to capture the current time within a loop. In the case of the <span class=\"tt\">@NowUTC<\/span> parameter being optional, it would have to be valued within the procedure, for example like this:\n<\/p>\n<div>\n[sql]\nCREATE PROCEDURE Person.CreateTemporaryPassword<br \/>\n  @PersonId INT,<br \/>\n  @NowUTC DATETIME2 = NULL<br \/>\nAS<br \/>\nBEGIN<br \/>\n  SET @NowUTC = COALESCE(@NowUTC,SYSUTCDATETIME());<\/p>\n<p>-- [other functionality here]\nEND<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nInstead of directly calling <span class=\"tt\">SYSDATETIME()<\/span> here, I recommend that call to be wrapped in a function:\n<\/p>\n<div>\n[sql]\nCREATE FUNCTION Util.CurrentDateTime()<br \/>\nRETURNS TABLE<br \/>\nAS<br \/>\nRETURN SELECT SYSUTCDATETIME() AS NowUTC;<br \/>\n[\/sql]\n<\/div>\n<div>\n[sql]\nCREATE PROCEDURE Person.CreateTemporaryPassword<br \/>\n  @PersonId INT,<br \/>\n  @NowUTC DATETIME2 = NULL<br \/>\nAS<br \/>\nBEGIN<br \/>\n  SELECT @NowUTC = COALESCE(@NowUTC,N.NowUTC)<br \/>\n    FROM Util.CurrentDateTime() AS N;<\/p>\n<p>-- [other functionality here]\nEND<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nIn a test we can no use <span class=\"tt\">tSQLt.FakeFunction<\/span> to replace that function with one that returns a hardcoded value:\n<\/p>\n<div>\n[sql]\nCREATE FUNCTION TimeDependentTests.[return 2015-01-07T09:57:15.1234567]()<br \/>\nRETURNS TABLE<br \/>\nAS<br \/>\nRETURN SELECT CAST('2015-01-07T09:57:15.1234567' AS DATETIME2) AS NowUTC;<br \/>\n[\/sql]\n<\/div>\n<div>\n[sql]\nCREATE PROCEDURE TimeDependentTests.[test example with wrapped SYSDATETIME()]\nAS<br \/>\nBEGIN<br \/>\n  EXEC tSQLt.FakeTable @TableName = 'Person.TempPasswords';<br \/>\n  EXEC tSQLt.FakeFunction<br \/>\n         @FunctionName = 'Util.CurrentDateTime',<br \/>\n         @FakeFunctionName = 'TimeDependentTests.[return 2015-01-07T09:57:15.1234567]';<\/p>\n<p>  EXEC Person.CreateTemporaryPassword @PersonId = 2346;<\/p>\n<p>  SELECT ExpirationDTime<br \/>\n    INTO #Actual<br \/>\n    FROM Person.TempPasswords;<\/p>\n<p>  SELECT TOP(0) *<br \/>\n  INTO #Expected<br \/>\n  FROM #Actual;<\/p>\n<p>  INSERT INTO #Expected<br \/>\n  VALUES('2015-01-07T10:12:15.1234567');<\/p>\n<p>  EXEC tSQLt.AssertEqualsTable '#Expected','#Actual';<br \/>\nEND;<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nThis type of wrapping is a very common technique in object-oriented design. In SQL Server, we have the complication that we have to be concerned with performance at all times. However, the impact of wrapping a system function like <span class=\"tt\">SYSDATETIME<\/span> into an <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/ms189294%28v=sql.105%29.aspx\" target=\"msdn\">inline table valued function<\/a> is very small. While it is certainly measurable, in most real life scenarios is it negligible.\n<\/p>\n<h3>Bracketing<\/h3>\n<p>\nThere are a few cases where you cannot take either approach discussed before. For example, you have to test the <span class=\"tt\">Util.CurrentDatetime<\/span> function at some point. Or, you might be in a situation where you have to test some existing code that for one or the other reason cannot be changed at the current time. In that case, you can use bracketing.\n<\/p>\n<p>\nBracketing is a testing technique that takes a timestamp immediately before and after an event like a procedure call. Anything that happened in that procedure call happened between those two time stamps. That means that any call to e.g. <span class=\"tt\">SYSUTCDATETIME()<\/span> within that procedure must have also returned a time between those two recorded timestamps. That however we can assert in a test:\n<\/p>\n<div>\n[sql]\nCREATE PROCEDURE TimeDependentTests.[test example with bracketing]\nAS<br \/>\nBEGIN<br \/>\n  DECLARE @actual DATETIME2;<br \/>\n  DECLARE @after DATETIME2;<br \/>\n  DECLARE @before DATETIME2;<\/p>\n<p>  SET @before = SYSUTCDATETIME();  <\/p>\n<p>  SELECT  @actual = N.NowUTC<br \/>\n    FROM Util.CurrentDateTime() AS N;<\/p>\n<p>  SET @after = SYSUTCDATETIME();  <\/p>\n<p>  IF(@actual &lt; @before OR @actual &gt; @after OR @actual IS NULL)<br \/>\n  BEGIN<br \/>\n    DECLARE @msg NVARCHAR(MAX) =<br \/>\n      'Expected:'+<br \/>\n      CONVERT(NVARCHAR(MAX),@before,121)+<br \/>\n      ' &lt;= '+<br \/>\n      ISNULL(CONVERT(NVARCHAR(MAX),@actual,121),'!NULL!')+<br \/>\n      ' &lt;= '+<br \/>\n      CONVERT(NVARCHAR(MAX),@after,121);<br \/>\n      EXEC tSQLt.Fail @msg;<br \/>\n  END;<\/p>\n<p>END;<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nThis test pattern is robust and it will not lead to fragile tests. However, you still have a certain uncertainty factor, particularly if the procedure you are testing is longer. In addition, this type of test tends to become very convoluted quickly. That is particularly the case, if you cannot directly access the used <span class=\"tt\">DATETIME2<\/span> value and have to use indirect measures instead. Therefore, I recommend using this pattern only for very simple functions and procedures. Functions that just wrap a system call are well fitting candidates for this unit testing approach.\n<\/p>\n<h3>Final Thoughts<\/h3>\n<p>\nThere are several ways to deal with time dependencies in unit tests. In this article, I demonstrated three of them that together give you a robust solution for almost any time dependent unit test situation. Whenever possible, add a parameter to any time dependent module to allow the current time or date to be passed in. That makes life easier in many situations, not only during unit test creation.\n<\/p>\n<p>\nYou might have noticed me using <span class=\"tt\">SYSUTCDATETIME()<\/span> instead of <span class=\"tt\">SYSDATETIME()<\/span>. UTC stands for Coordinated Universal Time (French: temps universel coordonn\u00e9). UTC time is the same across the entire globe and not dependent on the time zone you are in. In fact, it is the only time that is affected neither by time zones nor by daylight savings. Both, time zone calculations and daylight savings can cause complexities and ambiguities that can be easily avoided by storing every time as UTC. Believe me, it is a lot easier to convert a stored UTC time into the correct display time zone at runtime than it is to fix corrupt data in the database because a developer did not anticipate that there is one day a year on which 2:17 AM happens twice.\n<\/p>\n<p>\nYou also might have thought my timestamps look funny. That is another ambiguity-avoiding tactic. The format <span class=\"tt\">YYYY-MM-DDTHH:MM:SS.FFFFFFF<\/span> with a \"T\" between the date and the time is the only format that is interpreted the same way by SQL Server, independent of settings like the local language. It also is universally understood by people around the globe whereas \"05\/03\/2015 9:15\" is ambiguous to many.\n<\/p>\n<p>\nUsing these two pieces of advice, you can save yourself the hassle of test cases failing because your colleague in e.g. India used a different time zone or language setting.\n<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Testing functionality dependent on the current time or date commonly leads to fragile tests. Discover three proven test patterns to avoid that trap.<\/p>\n<p> <a href=\"https:\/\/sqlity.net\/en\/2811\/testing-time\/\">[more&#8230;]<\/a><\/p>\n","protected":false},"author":3,"featured_media":2812,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[246,5,27,25,12],"tags":[247,15,272,67],"class_list":["post-2811","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fragile-tests","category-general","category-series","category-tdd","category-tsqlt","tag-fragile-test","tag-sql-server","tag-tdd","tag-unit-test"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Testing Time - Three Ways to Avoid Fragile Tests - sqlity.net<\/title>\n<meta name=\"description\" content=\"Testing functionality dependent on the current time or date commonly leads to fragile tests. Discover three proven test patterns to avoid that trap.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sqlity.net\/en\/2811\/testing-time\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Testing Time - Three Ways to Avoid Fragile Tests - sqlity.net\" \/>\n<meta property=\"og:description\" content=\"Testing functionality dependent on the current time or date commonly leads to fragile tests. Discover three proven test patterns to avoid that trap.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sqlity.net\/en\/2811\/testing-time\/\" \/>\n<meta property=\"og:site_name\" content=\"sqlity.net\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/sqlity.net\" \/>\n<meta property=\"article:published_time\" content=\"2015-01-08T03:00:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"361\" \/>\n\t<meta property=\"og:image:height\" content=\"450\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Sebastian Meine\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@sqlity\" \/>\n<meta name=\"twitter:site\" content=\"@sqlity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sebastian Meine\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/\"},\"author\":{\"name\":\"Sebastian Meine\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\"},\"headline\":\"Testing Time &#8211; Three Ways to Avoid Fragile Tests\",\"datePublished\":\"2015-01-08T03:00:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/\"},\"wordCount\":1748,\"commentCount\":2,\"image\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2015\\\/01\\\/testing_time.jpg\",\"keywords\":[\"fragile test\",\"SQL Server\",\"TDD\",\"unit test\"],\"articleSection\":[\"Fragile Tests\",\"General\",\"Series\",\"TDD\",\"tSQLt\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/\",\"url\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/\",\"name\":\"Testing Time - Three Ways to Avoid Fragile Tests - sqlity.net\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2015\\\/01\\\/testing_time.jpg\",\"datePublished\":\"2015-01-08T03:00:15+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\"},\"description\":\"Testing functionality dependent on the current time or date commonly leads to fragile tests. Discover three proven test patterns to avoid that trap.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#primaryimage\",\"url\":\"https:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2015\\\/01\\\/testing_time.jpg\",\"contentUrl\":\"https:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2015\\\/01\\\/testing_time.jpg\",\"width\":361,\"height\":450,\"caption\":\"Testing Time\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/2811\\\/testing-time\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/sqlity.net\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Testing Time &#8211; Three Ways to Avoid Fragile Tests\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/sqlity.net\\\/en\\\/\",\"name\":\"sqlity.net\",\"description\":\"Quality for SQL\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/sqlity.net\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\",\"name\":\"Sebastian Meine\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"caption\":\"Sebastian Meine\"},\"sameAs\":[\"http:\\\/\\\/sqlity.net\",\"https:\\\/\\\/x.com\\\/sqlity\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Testing Time - Three Ways to Avoid Fragile Tests - sqlity.net","description":"Testing functionality dependent on the current time or date commonly leads to fragile tests. Discover three proven test patterns to avoid that trap.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sqlity.net\/en\/2811\/testing-time\/","og_locale":"en_US","og_type":"article","og_title":"Testing Time - Three Ways to Avoid Fragile Tests - sqlity.net","og_description":"Testing functionality dependent on the current time or date commonly leads to fragile tests. Discover three proven test patterns to avoid that trap.","og_url":"https:\/\/sqlity.net\/en\/2811\/testing-time\/","og_site_name":"sqlity.net","article_publisher":"https:\/\/www.facebook.com\/sqlity.net","article_published_time":"2015-01-08T03:00:15+00:00","og_image":[{"width":361,"height":450,"url":"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg","type":"image\/jpeg"}],"author":"Sebastian Meine","twitter_card":"summary_large_image","twitter_creator":"@sqlity","twitter_site":"@sqlity","twitter_misc":{"Written by":"Sebastian Meine","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/#article","isPartOf":{"@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/"},"author":{"name":"Sebastian Meine","@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c"},"headline":"Testing Time &#8211; Three Ways to Avoid Fragile Tests","datePublished":"2015-01-08T03:00:15+00:00","mainEntityOfPage":{"@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/"},"wordCount":1748,"commentCount":2,"image":{"@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/#primaryimage"},"thumbnailUrl":"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg","keywords":["fragile test","SQL Server","TDD","unit test"],"articleSection":["Fragile Tests","General","Series","TDD","tSQLt"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/sqlity.net\/en\/2811\/testing-time\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/","url":"https:\/\/sqlity.net\/en\/2811\/testing-time\/","name":"Testing Time - Three Ways to Avoid Fragile Tests - sqlity.net","isPartOf":{"@id":"https:\/\/sqlity.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/#primaryimage"},"image":{"@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/#primaryimage"},"thumbnailUrl":"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg","datePublished":"2015-01-08T03:00:15+00:00","author":{"@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c"},"description":"Testing functionality dependent on the current time or date commonly leads to fragile tests. Discover three proven test patterns to avoid that trap.","breadcrumb":{"@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sqlity.net\/en\/2811\/testing-time\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/#primaryimage","url":"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg","contentUrl":"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg","width":361,"height":450,"caption":"Testing Time"},{"@type":"BreadcrumbList","@id":"https:\/\/sqlity.net\/en\/2811\/testing-time\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/sqlity.net\/en\/"},{"@type":"ListItem","position":2,"name":"Testing Time &#8211; Three Ways to Avoid Fragile Tests"}]},{"@type":"WebSite","@id":"https:\/\/sqlity.net\/en\/#website","url":"https:\/\/sqlity.net\/en\/","name":"sqlity.net","description":"Quality for SQL","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sqlity.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c","name":"Sebastian Meine","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","caption":"Sebastian Meine"},"sameAs":["http:\/\/sqlity.net","https:\/\/x.com\/sqlity"]}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/sqlity.net\/wp-content\/uploads\/2015\/01\/testing_time.jpg","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2wXuw-Jl","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts\/2811","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/comments?post=2811"}],"version-history":[{"count":0,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts\/2811\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/media\/2812"}],"wp:attachment":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/media?parent=2811"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/categories?post=2811"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/tags?post=2811"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}