I am writing unit tests for my Java program. My program does a lot of things that involve reading from a file that the user inputs and creating a new file based on the contents of the inputted file.
Currently, my unit tests are using premade files made for testing that I've placed in the resources source directory. When it creates a file, it places it in the same resources source directory.
I've looked at a lot of questions and answers on here, and there are so many varying opinions on how to handle files in unit tests. Is it proper to use these premade files within my unit tests, or is there a better solution?
Yes, the standard practice is to place your static input files for testing in the src/test/resources directory. If you main code generates output, the cleanest place to put it during testing is in your platform-specific tmp directory. In Java, this is under the System property java.io.tmpdir:
System.out.println(System.getProperty("java.io.tmpdir"));
If you use this directory, it will be portable between developers running it under MacOS, Linux, or Windows - as well as any build server.
It is also a good idea for your test to delete these temporary files when the test is complete, and for your test to not make any assumption about temporary files that may exist from a previous test run.
Whether or not static "premade" files are appropriate largely depends on the logic you're trying to test and how you want to manage your test data. Perhaps you need test data that contains a date that is relative to today's date. In this case using a static file could be more trouble than writing code to calculate a relative date.
As JB Nizet pointed out in his comment it's generally not a good idea to store test data alongside your source code. I'm not sure if you're familiar with maven and its standard directory layout but you might take a look at it and see how it helps keep the test and source files separated.
Related
I am handling below way to work with files.
1st Approach:
I am keeping my files in D:\Projects\JavaProjects\LearnCucumber\src\test\resources\
-With the help of ClassLoader, I am getting the path and working on files
ResourceUtils.class.getClassLoader().getResource(".").getPath();
2nd Approach:
Now, I keep file in D:\Projects\JavaProjects\LearnCucumber\BrowserDrivers\
using System.getProperty("user.dir") I am dealing with files in this approach.
Now Which approach is efficient, when we run our code in different platform(windows,linux) in terms of handling files. Does it really makes difference?
Try to avoid working with files on the filesystem as those are usually less portable from one operating system to the next one. Also if you put files at certain locations other users of your software need to have those files available at the same location as well, whereas with your approach #1 you can ship these files directly with your application (packaged as jar) and access it from the classpath easily.
I'm trying to set up some initial tests for a JavaFX application, but specifically, I want to try and test the TreeView component, and I'm wondering how best to isolate access to the file system so that it can be tested (without having a dependency on my own file system). This is the project that I'm trying to test: https://github.com/mfearby/magnificat (it's a very basic thing at the moment and all it does is show a TabPane with some TreeViews pointing to the file system).
When you change the selected tab, it writes to an INI file so that when the app loads, it can restore those tabs. So I'd like to be able to test that this works, but it would depend on my own file system structure. The only testing I've ever done is with RedGate SQL Test, so I've never tested a GUI app, so please forgive the newbie question.
Should I somehow alter my FileTreeItem class which uses java.io.File.listFiles() so that it uses a virtual file system when testing (perhaps with Jimfs)? If I do this, how do I modify my class so that it uses Jimfs when testing but java.io.File when not in testing? Should I set a global variable (eek!) and act accordingly within my FileTreeItem class? That sounds awful but I'm scratching my head just wondering how best to test file system access without creating an absolute abomination.
Is it right to even modify the application code in such a way to accommodate a testing tool (apart from good coding practises in general) or should it be up to the test framework to do all the fakery to get the app to function in a testable way?
Any advice or pointers to "the right way" to do this would be much appreciated.
Thanks.
Ask yourself what it is you're unit testing.
Are you actually unit testing the writing to file? Why? You shouldn't test the JVM, but trust that it has already been tested.
So if not that, then what are you testing?
The file format? I.e. what you write get be read and understood? That part can be unit tested by using ByteArrayOutputStream and ByteArrayInputStream instead, so refactor the code so you can test the writing/reading logic using byte streams when unit testing, but file streams when running code.
I'm trying to work with nio's way to read files from directory.
I've come across the java.nio.file.DirectoryStream
which is cool because now I don't need to maintain a list of files in the directory by myself and I like this idea.
Now, my code is going to be run inside the WAR so that it will read the resources (say some xml files) packed inside jars inside this WAR.
I couldn't find a good example of working with DirectoryStream like this. So my question is how can I use this approach (not necessarily this particular class of course) in my situation?
Maybe there are some thirdparties that provide the similar abstraction...
In addition I would like to test this code from my unit test (which means that ideally this code shouldn't really assume that it runs inside/outside the WAR if its possible of course).
Thanks and have a nice day
I would suggest creating a temporary folder and copying the needed resources into this directory. Now you can use the DirectoryStream-Class, because the files are placed in the filesystem.
I'm trying to find the best way to create automated testing for functional/acceptance/regression testing for some java applications. All the applications work in this way:
They read a File from a given folder
They write a new file in another format with the content of the input file.
They send to database some of the information of processed files.
They wait until a new file is left in the input folder.
This is a cyclic application, it never stops.
New files/formats are added continuously and several of our libraries are shared by all the formats. Manual testing is taking more and more cost with each new format. All the files are plain text files but with different format in the way data is saved.
We need a way/tool that could help us to automated the functional/acceptance/regression tests (specially QA tests).
The question is: What tool/way of testing can be used for this?
I was thinking in something that can left files in the input folder and compare what the application creates in output folder with an expected file. I donĀ“t know if this can be done easily with a tool or if we have to make all of this entirely.
I would use a generic functional test automation framework and use a set of libraries to read/parse/compare files. I am familiar with Robot Framework and there are some Python Libraries to read/compare files (some embedded in Robot itself, some elsewhere). That is very convenient and quite easy to use for QA Tests. Check out the demo project for a good start.
If you prefer to stick in the Java ecosystem, you might want to try Cucumber-jvm or JBehave.
I'm writing some jUnit tests that depend on data files. Where should those data files go? And how would I (in the jUnit tests) get the location of that directory?
In Python, I would use something similar to:
datadir = os.dirname(__file__) + "/data/"
Kind of depends on what you're using the data files for, but in general, just create a package and make sure it's on your classpath. To load a properties file from the "data" package, add a "MyData.props" file and you can use load a properties file like:
this.getClass().getClassLoader().getResourceAsStream("/data/MyData.props");
Again, not exactly sure if this answers your question since I'm not 100% sure what you're trying to do, but I hope it helps a little.
Keep your test data close to your test classes (same package). As todd.run suggested, use getResourceAsStream() to access your data files.