Being Cellfish

Stuff I wished I've found in some blog (and sometimes did)

Change of Address
This blog has moved to blog.cellfish.se.
Posts
  • Being Cellfish

    2008 Advent Calendar December 8th

    • 0 Comments
    
    
    1: public class Advent8 : IDisposable 2: { 3: private IFileUtil m_file; 4:   5: private void SetUp() 6: { 7: m_file = new FileUtil("SomeFile.txt"); 8: m_file.Create("CONTENT"); 9: } 10:   11: public void Dispose() 12: { 13: m_file.Delete(); 14: } 15:   16: [Fact] 17: public void TestReadOK() 18: { 19: SetUp(); 20: Assert.DoesNotThrow(() => { m_file.Read(); }); 21: } 22:   23: [Fact] 24: public void TestReadFails() 25: { 26: SetUp(); 27: m_file.Readable = false; 28: Assert.Throws<AccessViolationException>(() => { m_file.Read(); }); 29: } 30: }

    Unfortunately I've reintroduced the fact that the actual content is not verified for TestReadOK. And using a constant isn't something I want to do again. But since I'm calling the setup method explicitly I can modify it to accept the desired content. Wouldn't that be neat?

  • Being Cellfish

    2008 Advent Calendar December 7th

    • 0 Comments
    
    
    1: public class Advent7 : IDisposable 2: { 3: private IFileUtil m_file; 4: private const string m_content = "CONTENT"; 5:   6: public Advent7() 7: { 8: m_file = new FileUtil("SomeFile.txt"); 9: m_file.Create(m_content); 10: } 11:   12: public void Dispose() 13: { 14: m_file.Delete(); 15: } 16:   17: [Fact] 18: public void TestReadOK() 19: { 20: string content = ""; 21: Assert.DoesNotThrow(() => { content = m_file.Read(); }); 22: Assert.Equal<string>(m_content, content); 23: } 24:   25: [Fact] 26: public void TestReadFails() 27: { 28: m_file.Readable = false; 29: Assert.Throws<AccessViolationException>(() => { m_file.Read(); }); 30: } 31: }

    Having the expected content in a constant member is pretty convenient but if the class grows and gets a lot of tests I'll have to scroll quite a bit to see the actual value. Personally I think you should have all the information needed for the test local in the test. Also I'm not a big fan of using the unit test framework "setup" mechanism since the reader of the test must know that the framework executes a certain setup-method. Even though that is probably true most of the time I think it is better to explicitly call the setup method and make it visible exactly how the test is set up.

  • Being Cellfish

    2008 Advent Calendar December 6th

    • 0 Comments
    
    
    1: public class Advent6: IDisposable 2: { 3: private IFileUtil m_file; 4:   5: public Advent6() 6: { 7: m_file = new FileUtil("SomeFile.txt"); 8: m_file.Create("CONTENT"); 9: } 10:   11: public void Dispose() 12: { 13: m_file.Delete(); 14: } 15:   16: [Fact] 17: public void TestReadOK() 18: { 19: Assert.DoesNotThrow(() => { m_file.Read(); }); 20: } 21:   22: [Fact] 23: public void TestReadFails() 24: { 25: m_file.Readable = false; 26: Assert.Throws<AccessViolationException>(() => { m_file.Read(); }); 27: } 28: }

    With some redundant code broken out into the common setup method (the default constructor if you're not familiar with Xunit.net) there is another thing that bothers me about the TestReadOK-test. We're not actually verifying the content of the file. Let's fix that in the next version of this test.

  • Being Cellfish

    2008 Advent Calendar December 5th

    • 2 Comments
    
    
    1: public class Advent5 : IDisposable 2: { 3: private IFileUtil m_file; 4:   5: public void Dispose() 6: { 7: m_file.Delete(); 8: } 9:   10: [Fact] 11: public void TestReadOK() 12: { 13: // Create a test file 14: m_file = new FileUtil("SomeFile.txt"); 15: m_file.Create("CONTENT"); 16:   17: // Should be able to read file 18: Assert.DoesNotThrow(() => { m_file.Read(); }); 19: } 20:   21: [Fact] 22: public void TestReadFails() 23: { 24: // Create a test file 25: m_file = new FileUtil("SomeFile.txt"); 26: m_file.Create("CONTENT"); 27:   28: m_file.Readable = false; 29:   30: // Should NOT be able to read file. 31: Assert.Throws<AccessViolationException>(() => { m_file.Read(); }); 32: } 33: }

    Now we're using Xunit-net's clean up mechanism, the IDisposableinterface. We still got some redundant code in the setup part of each test. Next I'll refactor that.

  • Being Cellfish

    2008 Advent Calendar December 4th

    • 0 Comments
    
    
    1: public class Advent4 2: { 3: [Fact] 4: public void TestReadOK() 5: { 6: // Create a test file 7: IFileUtil file = new FileUtil("SomeFile.txt"); 8: file.Create("CONTENT"); 9:   10: // Should be able to read file 11: Assert.DoesNotThrow(() => { file.Read(); }); 12:   13: // Clean up 14: file.Delete(); 15: } 16:   17: [Fact] 18: public void TestReadFails() 19: { 20: // Create a test file 21: IFileUtil file = new FileUtil("SomeFile.txt"); 22: file.Create("CONTENT"); 23:   24: file.Readable = false; 25:   26: // Should NOT be able to read file. 27: Assert.Throws<AccessViolationException>(() => { file.Read(); }); 28:   29: // Clean up 30: file.Delete(); 31: } 32: }

    Now that the initial test has been split up into two tests. One testing reading a readable file and one testing an unreadable file. Now I got some redundant code I wanna get rid of. The first thing is the clean up code. It is not run if the test fails and that is probably a bad thing. So next I'll fix that.

  • Being Cellfish

    2008 Advent Calendar December 3rd

    • 0 Comments
    
    
    1: public class Advent3 2: { 3: [Fact] 4: public void TestRead() 5: { 6: // Create a test file 7: IFileUtil file = new FileUtil("SomeFile.txt"); 8: file.Create("CONTENT"); 9:   10: // Should be able to read file 11: Assert.DoesNotThrow(() => { file.Read(); }); 12:   13: file.Readable = false; 14:   15: // Should NOT be able to read file. 16: Assert.Throws<AccessViolationException>(() => { file.Read(); }); 17:   18: // Clean up 19: file.Delete(); 20: } 21: }

    Using XUnit.net asserts to verify exceptions is much better than what we did yesterday. Now the test starts to be small enough to be understood easily. But I think there is a major problem with this test. We're not only testing that we cannot read an unreadable file, I'm also verifying that I can read a readable file. I think this should be split up into two different tests and that is what will happen next.

  • Being Cellfish

    2008 Advent Calendar December 2nd

    • 0 Comments
    
    
    1: public class Advent2 2: { 3: [Fact] 4: public void TestRead() 5: { 6: // Create a test file 7: IFileUtil file = new FileUtil("SomeFile.txt"); 8: file.Create("CONTENT"); 9:   10: // Should be able to read file 11: try 12: { 13: file.Read(); 14: } 15: catch (Exception) 16: { 17: throw new AssertException("Unexpected exception thrown"); 18: } 19:   20: file.Readable = false; 21:   22: // Should NOT be able to read file. 23: try 24: { 25: file.Read(); 26: throw new AssertException("No exception thrown"); 27: } 28: catch (AccessViolationException) 29: { 30: } 31: catch (Exception) 32: { 33: throw new AssertException("Unexpected exception thrown"); 34: } 35:   36: // Clean up 37: file.Delete(); 38: } 39: }

    Now I've added a handler for unexpected exceptions but this is still a pretty cumbersome way to write tests verifying that exceptions are thrown or not correctly. Especially since Xunit.net provides us with a really simple way to handle this for us. That is what will happen next.

  • Being Cellfish

    2008 Advent Calendar December 1st

    • 1 Comments
    
    
    1: public class Advent1 2: { 3: [Fact] 4: public void TestRead() 5: { 6: // Create a test file 7: IFileUtil file = new FileUtil("SomeFile.txt"); 8: file.Create("CONTENT"); 9:   10: // Should be able to read file 11: try 12: { 13: file.Read(); 14: } 15: catch (Exception) 16: { 17: throw new AssertException("Unexpected exception thrown"); 18: } 19:   20: file.Readable = false; 21:   22: // Should NOT be able to read file. 23: try 24: { 25: file.Read(); 26: throw new AssertException("No exception thrown"); 27: } 28: catch (AccessViolationException) 29: { 30: } 31:   32: // Clean up 33: file.Delete(); 34: } 35: }

    With this first version of the test there I have not utilized all the features of Xunit.net. I basically do all the verification my self and create test failures by explicitly throwing AssertFailure exceptions. There are several problems with this code but the only problem that will be addressed in the next version of this test is if line 25 throws another exception than AccessViolationException. Xunit.net will save the day but it is quite ugly So in tomorrows version we'll fix that.

  • Being Cellfish

    The 2008 Advent Calendar situation

    • 2 Comments

    So for this year's Advent calendar I'll focus on a made up file utility object. The object is called FileUtil and it implements an interface called IFileUtil which looks like this:

        public interface IFileUtil
        {
            void Create(string content);
            void Delete();
            string Read();
            string Path { get; }
            bool Readable { get; set; }
        }
    
    I think the methods are quite straight forward but a quick walk-through:
    • Create creates a file with given content.
    • Delete deletes the file.
    • Read returns the content of the file.
    • Path returns the path to the file.
    • Readable indicates if the file is readable or not. It is also possible to change permissions (i.e. readable or not) using this property.

    The test I will write (in 24 different ways) is a test where I want to verify that the correct exception is thrown when I try to read a file that is not readable. And before I do that I want to make sure the file actually exists and is readable. So basically the test consist of the following steps:

    • Create a test file.
    • Make sure I can read that file.
    • Change the file from readable to not readable.
    • Make sure I can no longer read the file.
    • Remove the test file.
    All the tests are written using Xunit.net
  • Being Cellfish

    Advent Calendar 2008

    • 1 Comments

    A few weeks ago I was involved in a discussion where we looked at a number of different ways to write the same test. I was amazed of how simple it is to write even a simple test in several different ways, all with their own pros and cons. So I decided to create an Advent calendar on this topic this year... I don't know how Advent calendars work in countries where you celebrate Christmas day rather than Christmas eve which is the case in Sweden but I'll stick to the Swedish tradition.

    So, starting from December 1st I'll present a new way of writing the same test each day ending on Christmas eve. So you have 24 different versions of the same test to look forward to. The tests will not be strictly better in my opinion. Actually I'm not sure which one of the versions I like the most.

    I will also start the whole thing off on November 30th and present the interface I'll be testing and what the test I'm writing is supposed to do.

Page 42 of 49 (481 items) «4041424344»