Already quite a while ago I published the post
“How to test the finalizer code (c #)” , in which I shared the experience of testing the code implemented in the finalizer. Less than a year, as the test still fell. Details under the cut.
In short, the testing method was described, the finalizer code using the AppDomain:
[Test] public void TestTemporaryFile_without_Dispose() { const string DOMAIN_NAME = "testDomain"; const string FILENAME_KEY = "fileName"; string testRoot = Directory.GetCurrentDirectory(); AppDomainSetup info = new AppDomainSetup { ApplicationBase = testRoot }; AppDomain testDomain = AppDomain.CreateDomain(DOMAIN_NAME, null, info); testDomain.DoCallBack(delegate { MyTemporaryFile temporaryFile = new MyTemporaryFile(); Assert.IsTrue(File.Exists(temporaryFile.FileName)); AppDomain.CurrentDomain.SetData(FILENAME_KEY, temporaryFile.FileName); }); string createdTemporaryFileName = (string)testDomain.GetData(FILENAME_KEY); Assert.IsTrue(File.Exists(createdTemporaryFileName)); AppDomain.Unload(testDomain);
As the premonition wrote in the notes:
3. Most likely, the implementation of this test also has all sorts of subtle points, but many years of practice have never recorded the false triggering of this test.
')
Less than a year after the publication of this post and the test still fell in the line:
Assert.IsTrue(File.Exists(createdTemporaryFileName));
This line verifies that the file created in the domain still exists, although the object is already "no."
At first I didn’t even believe it: I launched it once, once again it passes. Then I ran the test with the
Repeat attribute:
[Test] [Repeat(1000)] public void TestTemporaryFile_without_Dispose() { ... }
and the test fell.
I experimented and got a test that drops 7-8 times in 1000 runs (0.7% -0.8%) on my computer.
If I understand correctly, then sometimes (quite rarely) the object's finalizer is called very quickly and this test just does not have time to make sure that the file still exists.
I had to refuse to check the existence of the file: now the test checks that there is no file after uploading the application domain (AppDomain.Unload).
Now, if we go further, I’ll expect this test to fail while checking for the absence of a file, because this file (standard temporary file) can be recreated by the operating system from another (parallel) test or, in general, by another program.
What am I doing wrong?
I have a problem, the process creates and destroys temporary files, the process can live for a long time, during this time, if badly created temporary files are deleted, they simply physically run out and another attempt to obtain a temporary file from the operating system will end in error.
So, I see the following options:
- check the random drop of this test once in a while;
- score on tests (check a couple of times with pens);
- do not use standard temporary files.