Loading ...
Sorry, an error occurred while loading the content.

How to unit test classes that interact directly with file system

Expand Messages
  • Derek Yang
    Hi, I m TDDing a small application that has a lot of interactions with file system. I m having an issue unit testing one of my classes - WindowsFileParser.
    Message 1 of 12 , Jun 21, 2006
    • 0 Attachment
      Hi,

      I'm TDDing a small application that has a lot of interactions with
      file system. I'm having an issue unit testing one of my classes -
      WindowsFileParser.

      This class's responsibility is simple: Iterates through a given
      directory, retrieves all the files and sub-directories, and puts them
      into a collection object. The client code looks something like this:

      IFileParser fileParser = new WindowsFileParser();
      fileParser.ParentDirectory = @"d:\FileParser\MultipleFiles";
      ArrayList fileInfoList = fileParser.FileInfoList;
      foreach (FileInfo fileInfo in fileInfoList)
      {
      // utilize fileInfo.FileName, fileInfo.FileSizeInKB, etc.
      }

      I want to write unit test code to make sure WindowsFileParser
      recognizes files and sub-directories correctly. In order to do this,
      I think I need to create a designated directory and file structure,
      and check the results to make sure fileInfoList contains correct
      information. But I don't want my unit test code to be coupled with a
      specific directory & file structure. Also, I want my unit test code
      to be able to run on any machines, therefore I'd really like to
      de-couple the unit test code from a specific directory & file
      structure on a specific machine.

      I am thinking creating the structure in the setup code, and cleaning
      it up in the teardown method. But I'm not sure if this is the
      recommended approach.

      Any suggestions please?
    • Neil Swingler
      ... I use the java tempfile facility (look at java.io.File). You can set the files to be deleted automatically when the vm exits. Directories are more
      Message 2 of 12 , Jun 22, 2006
      • 0 Attachment
        Derek Yang writes:

        > Hi,
        >
        > I'm TDDing a small application that has a lot of interactions with
        > file system. I'm having an issue unit testing one of my classes -
        > WindowsFileParser.
        >
        > This class's responsibility is simple: Iterates through a given
        > directory, retrieves all the files and sub-directories, and puts them
        > into a collection object. The client code looks something like this:
        >
        > IFileParser fileParser = new WindowsFileParser();
        > fileParser.ParentDirectory = @"d:\FileParser\MultipleFiles";
        > ArrayList fileInfoList = fileParser.FileInfoList;
        > foreach (FileInfo fileInfo in fileInfoList)
        > {
        > // utilize fileInfo.FileName, fileInfo.FileSizeInKB, etc.
        > }
        >
        > I want to write unit test code to make sure WindowsFileParser
        > recognizes files and sub-directories correctly. In order to do this,
        > I think I need to create a designated directory and file structure,
        > and check the results to make sure fileInfoList contains correct
        > information. But I don't want my unit test code to be coupled with a
        > specific directory & file structure. Also, I want my unit test code
        > to be able to run on any machines, therefore I'd really like to
        > de-couple the unit test code from a specific directory & file
        > structure on a specific machine.
        >
        > I am thinking creating the structure in the setup code, and cleaning
        > it up in the teardown method. But I'm not sure if this is the
        > recommended approach.
        >
        > Any suggestions please?

        I use the java tempfile facility (look at java.io.File). You can set the
        files to be deleted automatically when the vm exits. Directories are more
        difficult since there is no auto delete capability so you need to
        explicitely remove them in tearDown or just let the temp dir grow.

        - Neil
      • Neil Swingler
        ... Whoops you are obviously not using java - hope something similar exists in C# or whatever you use. - Neil
        Message 3 of 12 , Jun 22, 2006
        • 0 Attachment
          Neil Swingler writes:

          > Derek Yang writes:
          >
          >> Hi,
          >>
          >> I'm TDDing a small application that has a lot of interactions with
          >> file system. I'm having an issue unit testing one of my classes -
          >> WindowsFileParser.
          >>
          >> This class's responsibility is simple: Iterates through a given
          >> directory, retrieves all the files and sub-directories, and puts them
          >> into a collection object. The client code looks something like this:
          >>
          >> IFileParser fileParser = new WindowsFileParser();
          >> fileParser.ParentDirectory = @"d:\FileParser\MultipleFiles";
          >> ArrayList fileInfoList = fileParser.FileInfoList;
          >> foreach (FileInfo fileInfo in fileInfoList)
          >> {
          >> // utilize fileInfo.FileName, fileInfo.FileSizeInKB, etc.
          >> }
          >>
          >> I want to write unit test code to make sure WindowsFileParser
          >> recognizes files and sub-directories correctly. In order to do this,
          >> I think I need to create a designated directory and file structure,
          >> and check the results to make sure fileInfoList contains correct
          >> information. But I don't want my unit test code to be coupled with a
          >> specific directory & file structure. Also, I want my unit test code
          >> to be able to run on any machines, therefore I'd really like to
          >> de-couple the unit test code from a specific directory & file
          >> structure on a specific machine.
          >>
          >> I am thinking creating the structure in the setup code, and cleaning
          >> it up in the teardown method. But I'm not sure if this is the
          >> recommended approach.
          >>
          >> Any suggestions please?
          >
          > I use the java tempfile facility (look at java.io.File). You can set the
          > files to be deleted automatically when the vm exits. Directories are more
          > difficult since there is no auto delete capability so you need to
          > explicitely remove them in tearDown or just let the temp dir grow.
          >
          Whoops you are obviously not using java - hope something similar exists in
          C# or whatever you use.

          - Neil
        • Thomas Eyde
          Environment.CurrentDirectory returns the assembly s folder. You could use that as a base for your file structure. Perhaps you can use IsolatedStorage? I
          Message 4 of 12 , Jun 22, 2006
          • 0 Attachment
            Environment.CurrentDirectory returns the assembly's folder. You could use
            that as a base for your file structure.

            Perhaps you can use IsolatedStorage? I haven't tried it myself.

            --
            Thomas

            On 6/22/06, Neil Swingler <neil@...> wrote:
            >
            > > I use the java tempfile facility (look at java.io.File). You can set
            > the
            > > files to be deleted automatically when the vm exits. Directories are
            > more
            > > difficult since there is no auto delete capability so you need to
            > > explicitely remove them in tearDown or just let the temp dir grow.
            > >
            > Whoops you are obviously not using java - hope something similar exists in
            >
            > C# or whatever you use.
            >
            > - Neil
            > __._
            >


            [Non-text portions of this message have been removed]
          • Tim Haughton
            ... There are a couple of things you could do to make life easier. I m going to assume a few things, but you should be able to pick out what s true for you.
            Message 5 of 12 , Jun 22, 2006
            • 0 Attachment
              On 22/06/06, Derek Yang <derekhyang@...> wrote:
              > This class's responsibility is simple: Iterates through a given
              > directory, retrieves all the files and sub-directories, and puts them
              > into a collection object. The client code looks something like this:
              >
              > IFileParser fileParser = new WindowsFileParser();
              > fileParser.ParentDirectory = @"d:\FileParser\MultipleFiles";
              > ArrayList fileInfoList = fileParser.FileInfoList;
              > foreach (FileInfo fileInfo in fileInfoList)
              > {
              > // utilize fileInfo.FileName, fileInfo.FileSizeInKB, etc.
              > }
              >

              There are a couple of things you could do to make life easier. I'm
              going to assume a few things, but you should be able to pick out
              what's true for you.

              Firstly, I'd create an IWindowsFileParser interface, and have your
              WindowsFileParser implement it. I'd also want some way of injecting
              the WindowsFileParser into the client object. So, we can pass an
              IWindowsFileParser into a method, have a property to set it, use a
              factory, pass it into the ctor etc.

              This would mean we would be able to mock out the parser so that you
              can test the client code without having to touch the file system.

              To test the WindowsFileParser, we are going to have to be able to
              touch the file system, We can't mock out the .Net file system classes,
              and wrapping them would really just defer the solution.

              I would certainly have you set up and tear down methods create and
              destroy the classes. I can't think of a better way. I would be against
              having a predefined file structure that your tests couple to.

              If you find that your tests get slow, and if you're using a good
              framework like NUnit, then add a "Slow" category to those tests, and
              run them less frequently than your normal tests.

              --
              Regards,

              Tim Haughton

              http://agitek.co.uk
              http://blogitek.com/timhaughton
            • gregbalajewicz
              Perhaps I will be shut down for this but I say don t worry about this. Isolate as much of the code from the file system as possible, test that and forget about
              Message 6 of 12 , Jun 22, 2006
              • 0 Attachment
                Perhaps I will be shut down for this but I say don't worry about this.

                Isolate as much of the code from the file system as possible, test
                that and forget about auto-testing the code that does the actual
                interfacing to the file system.

                Some test cost more to create then they are worthÂ…

                OK everybody, I am ready - take your shots at the non-purist! ;)

                PS - creating a simple screen that displays the directory structure
                read in by your object and use it as a 'manual test' is also a good
                idea. Basically have one test that launches the screen and your
                object reads in some of the C drive and displays it on the screen.
                You can have this test to be in a special folder (in nunit) that you
                do not run on regular basis.

                --- In extremeprogramming@yahoogroups.com, "Derek Yang"
                <derekhyang@...> wrote:
                >
                > Hi,
                >
                > I'm TDDing a small application that has a lot of interactions with
                > file system. I'm having an issue unit testing one of my classes -
                > WindowsFileParser.
                >
                > This class's responsibility is simple: Iterates through a given
                > directory, retrieves all the files and sub-directories, and puts
                them
                > into a collection object. The client code looks something like
                this:
                >
                > IFileParser fileParser = new WindowsFileParser();
                > fileParser.ParentDirectory = @"d:\FileParser\MultipleFiles";
                > ArrayList fileInfoList = fileParser.FileInfoList;
                > foreach (FileInfo fileInfo in fileInfoList)
                > {
                > // utilize fileInfo.FileName, fileInfo.FileSizeInKB, etc.
                > }
                >
                > I want to write unit test code to make sure WindowsFileParser
                > recognizes files and sub-directories correctly. In order to do
                this,
                > I think I need to create a designated directory and file structure,
                > and check the results to make sure fileInfoList contains correct
                > information. But I don't want my unit test code to be coupled with
                a
                > specific directory & file structure. Also, I want my unit test code
                > to be able to run on any machines, therefore I'd really like to
                > de-couple the unit test code from a specific directory & file
                > structure on a specific machine.
                >
                > I am thinking creating the structure in the setup code, and cleaning
                > it up in the teardown method. But I'm not sure if this is the
                > recommended approach.
                >
                > Any suggestions please?
                >
              • Derek Yang
                ... Yes I did that. I used mocks to mock out the behavior of the interface (I named it as IFileParser because I am planning to implement a OSXFileParser in a
                Message 7 of 12 , Jun 22, 2006
                • 0 Attachment
                  --- In extremeprogramming@yahoogroups.com, "Tim Haughton"
                  <timhaughton@...> wrote:

                  > Firstly, I'd create an IWindowsFileParser interface, and have your
                  > WindowsFileParser implement it. I'd also want some way of injecting
                  > the WindowsFileParser into the client object. So, we can pass an
                  > IWindowsFileParser into a method, have a property to set it, use a
                  > factory, pass it into the ctor etc.
                  >
                  > This would mean we would be able to mock out the parser so that you
                  > can test the client code without having to touch the file system.

                  Yes I did that. I used mocks to mock out the behavior of the
                  interface (I named it as IFileParser because I am planning to
                  implement a OSXFileParser in a few weeks), and injected the mocked
                  instance into the client code which needs to interact with a file
                  system implementation (but doesn't need to be a real one).

                  > To test the WindowsFileParser, we are going to have to be able to
                  > touch the file system, We can't mock out the .Net file system classes,
                  > and wrapping them would really just defer the solution.
                  >
                  > I would certainly have you set up and tear down methods create and
                  > destroy the classes. I can't think of a better way. I would be against
                  > having a predefined file structure that your tests couple to.

                  Thanks, I might end up taking this approach.

                  > If you find that your tests get slow, and if you're using a good
                  > framework like NUnit, then add a "Slow" category to those tests, and
                  > run them less frequently than your normal tests.

                  Frankly I don't know this feature in NUnit before. But I will
                  definitely try it out. Thanks a lot!
                • Derek Yang
                  ... set the ... are more ... exists in ... Yes I am using C# for this particular app. No I didn t find a C#/.NET counterpart of the tempfile facility you
                  Message 8 of 12 , Jun 22, 2006
                  • 0 Attachment
                    --- In extremeprogramming@yahoogroups.com, "Neil Swingler" <neil@...>
                    wrote:

                    > > I use the java tempfile facility (look at java.io.File). You can
                    set the
                    > > files to be deleted automatically when the vm exits. Directories
                    are more
                    > > difficult since there is no auto delete capability so you need to
                    > > explicitely remove them in tearDown or just let the temp dir grow.
                    > >
                    > Whoops you are obviously not using java - hope something similar
                    exists in
                    > C# or whatever you use.
                    >
                    > - Neil
                    >

                    Yes I am using C# for this particular app. No I didn't find a C#/.NET
                    counterpart of the tempfile facility you mentioned. But it's good to
                    know about it.

                    This sounds similar to the idea of preparing the test environment in
                    SetUp and cleaning it up in TearDown. I'm thinking about it. This
                    might be the path I end up taking...

                    Thx!
                  • Rob Park
                    We have 1 project that uses files to store its data (on a PDA). 1st, we have isolated the file access to an implementation of a DAO. We do test the DAO
                    Message 9 of 12 , Jun 23, 2006
                    • 0 Attachment
                      We have 1 project that uses files to store its data (on a PDA).

                      1st, we have isolated the file access to an implementation of a DAO. We do
                      test the DAO directly including creating the directory and the file in the
                      [SetUp]. We don't cleanup anything in the [TearDown]. We tend to follow
                      the guideline that it's each tests responsiblility to cleanup what it
                      doesn't want, setup what it does want before it runs itself.

                      rob.

                      _____

                      From: extremeprogramming@yahoogroups.com
                      [mailto:extremeprogramming@yahoogroups.com] On Behalf Of Derek Yang
                      Sent: Thursday, June 22, 2006 12:21 AM
                      To: extremeprogramming@yahoogroups.com
                      Subject: [XP] How to unit test classes that interact directly with file
                      system



                      Hi,

                      I'm TDDing a small application that has a lot of interactions with
                      file system. I'm having an issue unit testing one of my classes -
                      WindowsFileParser.

                      This class's responsibility is simple: Iterates through a given
                      directory, retrieves all the files and sub-directories, and puts them
                      into a collection object. The client code looks something like this:

                      IFileParser fileParser = new WindowsFileParser();
                      fileParser.ParentDirectory = @"d:\FileParser\MultipleFiles";
                      ArrayList fileInfoList = fileParser.FileInfoList;
                      foreach (FileInfo fileInfo in fileInfoList)
                      {
                      // utilize fileInfo.FileName, fileInfo.FileSizeInKB, etc.
                      }

                      I want to write unit test code to make sure WindowsFileParser
                      recognizes files and sub-directories correctly. In order to do this,
                      I think I need to create a designated directory and file structure,
                      and check the results to make sure fileInfoList contains correct
                      information. But I don't want my unit test code to be coupled with a
                      specific directory & file structure. Also, I want my unit test code
                      to be able to run on any machines, therefore I'd really like to
                      de-couple the unit test code from a specific directory & file
                      structure on a specific machine.

                      I am thinking creating the structure in the setup code, and cleaning
                      it up in the teardown method. But I'm not sure if this is the
                      recommended approach.

                      Any suggestions please?






                      [Non-text portions of this message have been removed]
                    • Sammy Larbi
                      ... I think I like that idea. ... Now, don t think I m being a moron (even though I probably am). I m unfamiliar here, so I want to ask why not? Is it
                      Message 10 of 12 , Jun 28, 2006
                      • 0 Attachment
                        Tim Haughton wrote:

                        > This would mean we would be able to mock out the parser so that you
                        > can test the client code without having to touch the file system.
                        >
                        >
                        I think I like that idea.
                        > To test the WindowsFileParser, we are going to have to be able to
                        > touch the file system, We can't mock out the .Net file system classes,
                        > and wrapping them would really just defer the solution.
                        >
                        >
                        Now, don't think I'm being a moron (even though I probably am). I'm
                        unfamiliar here, so I want to ask "why not?" Is it forbidden? I would
                        think (as long as it is not forbidden) that this would be the most
                        preferable method.

                        > I would certainly have you set up and tear down methods create and
                        > destroy the classes. I can't think of a better way. I would be against
                        > having a predefined file structure that your tests couple to.
                        >
                        >
                        Most definitely don't do that. But I wouldn't mind so much if the tests
                        defined a file structure to test on (in fact, how else would you know
                        your test is really passing or failing?). That was probably assumed.
                        Just don't run them on a machine that means anything to you (what if you
                        accidentally called format?) Or I imagine if you set up a really strong
                        sandbox, it might work fine.
                      • Tim Haughton
                        ... Assuming we re using a run-of-the-mill mocking framework, we can only mock virtuals and interfaces. From memory, the file system objects don t have them.
                        Message 11 of 12 , Jun 28, 2006
                        • 0 Attachment
                          On 28/06/06, Sammy Larbi <sam@...> wrote:
                          > Tim Haughton wrote:
                          >
                          > > To test the WindowsFileParser, we are going to have to be able to
                          > > touch the file system, We can't mock out the .Net file system classes,
                          > > and wrapping them would really just defer the solution.
                          > >
                          > >
                          > Now, don't think I'm being a moron (even though I probably am). I'm
                          > unfamiliar here, so I want to ask "why not?" Is it forbidden? I would
                          > think (as long as it is not forbidden) that this would be the most
                          > preferable method.

                          Assuming we're using a run-of-the-mill mocking framework, we can only
                          mock virtuals and interfaces. From memory, the file system objects
                          don't have them.

                          > Most definitely don't do that. But I wouldn't mind so much if the tests
                          > defined a file structure to test on (in fact, how else would you know
                          > your test is really passing or failing?).

                          I'm not sure what you mean here. Can you elaborate?

                          --
                          Regards,

                          Tim Haughton

                          http://agitek.co.uk
                          http://blogitek.com/timhaughton
                        • Sammy Larbi
                          Sorry it took me so long, I ve gotten a bit behind. ... I was thinking you could inherit from and override the methods you need to test. Didn t know if that
                          Message 12 of 12 , Jul 3, 2006
                          • 0 Attachment
                            Sorry it took me so long, I've gotten a bit behind.

                            Tim Haughton wrote:
                            >> Now, don't think I'm being a moron (even though I probably am). I'm
                            >> unfamiliar here, so I want to ask "why not?" Is it forbidden? I would
                            >> think (as long as it is not forbidden) that this would be the most
                            >> preferable method.
                            >>
                            >
                            > Assuming we're using a run-of-the-mill mocking framework, we can only
                            > mock virtuals and interfaces. From memory, the file system objects
                            > don't have them.
                            >
                            >
                            I was thinking you could inherit from and override the methods you need
                            to test. Didn't know if that would work or not.
                            >> Most definitely don't do that. But I wouldn't mind so much if the tests
                            >> defined a file structure to test on (in fact, how else would you know
                            >> your test is really passing or failing?).
                            >>
                            >
                            > I'm not sure what you mean here. Can you elaborate?
                            >
                            >
                            I was simply saying rather than having a predefined file structure, you
                            can have the tests define it. For instance, you wouldn't have a
                            directory set up like "C:\app\test\someDirectory" where the unit tests
                            called it. Rather, you would have (psuedocode):

                            setUp()
                            {
                            workingDir=createDir(currentDir + "\someDirectory");
                            }
                            testMoveFile()
                            {
                            createFile(workingDir,fileName);
                            assertFileExists(workingDir+fileName);
                            }
                            tearDown()
                            {
                            removeDir(workingDir);
                            }

                            So it sets it up and tears it down, and you can move it anywhere you want.




                            [Non-text portions of this message have been removed]
                          Your message has been successfully submitted and would be delivered to recipients shortly.