File handling in UWP unit tests - unit-testing

I have to setup some unit tests to run on UWP. The unit tests work with files on disk. The files location is configured as a full path (C:\Temp\ for example).
I created a unit test application in Visual Studio 2015, in application manifest I checked Internet (Client), Private Networks and Removable Storage. I also setup a file association for my file type (.dat).
When I run the tests I get Access Denied exceptions when the tests try to open the files on disk. The files are opened using the FileStream class.
Exception Message: Test method UnitTests.TestMethod1 threw exception:
System.UnauthorizedAccessException: Access to the path 'C:\Temp\file.dat' is denied.
How can I setup the test application to be able to open arbitrary files on disk?
Update:
This is a sample test:
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// 1. Open the file using a FileStream
FileStream fs = new FileStream("C:\\Temp\\file.dat", FileMode.Open, FileAccess.Read, FileShare.Read);
// or
// 2. Open the file using UWP file API
Task<Stream> ts = GetStream();
Stream s = ts.Result;
}
async private Task<Stream> GetStream()
{
Windows.Storage.StorageFile sf = await Windows.Storage.StorageFile.GetFileFromPathAsync("C:\\Temp\\file.dat");
Stream s = await sf.OpenStreamForReadAsync();
return s;
}
}
At this moment, after further study, I believe it is not possible to open programmatically arbitrary files on disk from an UWP (test) application, you have to use a file picker to select a file and then open it.

I assume you need a fixed sample of pictures to test your app. I would try to add these samples to lets say Assets folder of your unit test app. Then for every sample file in the Assets folder you want use for testing set the properties such that
Build actions = "Content". This will add the file to the App directory after the build. Then you can access your files like this:
StorageFolder assets = await Package.Current.InstalledLocation.GetFolderAsync("Assets");
StorageFile myTestFile = await assets.GetFileAsync("file1.jpeg");
This in fact ensures, that the test samples are always in the sandbox of your application.
Of course, if you are testing some kind of processing, you can first copy your files from the Assets to the root folder of the App in the [TestInitialize] method and after finishing the tests delete them in [TestFinalize] section. I am using this approach for testing some DB operations on SQLite database (which I move from Assets to root as a file and after the test I delete it). It works for me (VS 2017 UWP app) so it should for you too.

You can run your test once. Then got to Settings|Apps & Features and find your UnitTest project on the test machine. Then grant file permissions there.
This is not ideal, because it is not practical on a Build server.

Related

How to read a file on Hololens with C++

I am trying to read a file in a test/debug UWP application that is being deployed to Hololens. I can put the file on the device with the device portal, but am unable to find the correct path to open the file.
I am using the MSFT BasicXrApp_uwp example as a basis, and have included FileUtility which has a FindFileInAppFolder function. This is consistently failing to find the file, with the error:
"The file should be embeded in app folder in debug build.",
after letting me know the app folder is:
C:\Data\Users\DefaultAccount\AppData\Local\DevelopmentFiles\364f83f4-6e13-42e4-8253-71dd3040951cVS.Debug_ARM.mikeh\
The part 364f83f4-6e13-42e4-8253-71dd3040951cVS is recognisable in the device portal as the User Folders/LocalAppData folder, but the Debug_ARM.mikeh part is not visible on the portal.
I am using C++ and trying to do the file reading in a static, non uwp library if possible (pointing that out so I don't get suggestions to use UWP async stuff, if that is possible).
So, how do I embed my file in the app folder, or how do I place the file so I can read it?
This is because the folder path which FindFileInAppFolder method returns is the InstalledLocation of the current package, but what you checked in the device portal is LocalFolder/LocalCacheFolder, for more information about what different between them please see: File access permissions.
how do I embed my file in the app folder, or how do I place the file so I can read it?
You can place your file in the LocalState folder by Device Portal and get this folder path through ApplicationData.LocalFolder Property, the path should be like: C:\Data\Users\DefaultAccount\AppData\Local\Packages\364f83f4-6e13-42e4-8253-71dd3040951c\LocalState. For how to access the files via C++ you can use for example File access sample
I'm using an answer here as there's more room than a comment.
I found a few extra things useful. I added in the cppWinRT nuget package to my application.
I did need to use the "async stuff", for example:
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;
StorageFolder storageFolder= KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::PicturesLibrary).get();
This let me find a file I'd uploaded ot the Pictures Library. But I couldn't open it after passing the path to my existing library:
const auto sampleFile = storageFolder.GetFileAsync(fileName).get();
std::wstring path = sampleFile.Path();
MyLibraryCall(to_string(path));
MyLibraryCall would try and open an ifstream, and even using std::ifstream::in would fail.
So I copied the file to the temp directory, where I could open it and process it.
This is pretty hacky but it did what I needed, which is let me load an .obj file that was rejected by the 3D parts viewer.
The loop over all filenames is because storageFolder.GetFileAsync(fileName).get() throws an exception if it fails, which for me I could not catch properly.
StorageFolder tempFolder = Windows::Storage::ApplicationData::Current().TemporaryFolder();
std::wstring path;
auto files = tempFolder.GetFilesAsync().get();
for (auto file : files)
{
if (file.Name() == fileName) {
path = file.Path();
break;
}
}
if (!path.size()) {
// hasn't been copied into temp
StorageFile movedFile = sampleFile.CopyAsync(tempFolder).get();
path = movedFile.Path();
}
MyLibraryCall(to_string(path));
Anyway- not the greatest but that will hopefully help someone else looking for a quick and dirty way to process a file on a hololens/UWP app.

how to copy a .db file from assets to FileSystem in expo

Expo SDK Version: 36.0.0
Platform: iOS Simulator
I need to copy a .db file from assets to the FileSystem.documentDirectory but I get an error. Here's the code I'm trying:
await FileSystem.downloadAsync(
Asset.fromModule(require('../assets/databases/data.db')).uri,
`${FileSystem.documentDirectory}SQLite/data.db`
);
Here's the error I get:
Unable to resolve module "../assets/databases/data.db"
None of these files exist:
* assets/databases/data.db(.native|.ios.expo.ts|.native.expo.tx|.expo.ts|.ios.expo.tsx|.native.expo.tsx|.expo.tsx|.ios.expo.js|.native.expo.js|.expo.js|.ios.expo.jsx|.native.expo.jsx|.expo.jsx|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.wasm|.native.wasm|.wasm)
How do i copy a .db file from assets to the FileSystem.documentDirectory folder? I just need to copy a .db file from assets to the FileSystem.documentDirectory folder, but this error makes it look like Asset.fromModule only allows image files.
If I use the exact same code but replace the .db file with a .png file, it works.
Expo SDK Version: 36.0.0
Platform: android expo client sdk-qr code
i am also need this db file and i dont understand how to get it ..
my code here just give me the path ..but no have path like that , i just want to see my db file and i want to save this file in my desktop . how can i do that ?
const { uri } = await FileSystem.getInfoAsync(
`${FileSystem.documentDirectory}SQLite/${'places.db'}`
)
console.log("THIS IS PATH OF THE DB",uri)
I found the answer from a combination of expo forum posts, primarily this one: https://forums.expo.io/t/unable-to-load-obj-file-using-require/15794/3
The problem is that by default, the expo Assets api doesn't recognize .db files, so you have to create a file in the root of your project called metro.config.js and then add the following code to the file:
module.exports = {
resolver: {
assetExts: ["db", "ttf", "png"]
}
};
After that, you can then do this and it will work:
await FileSystem.downloadAsync(
Asset.fromModule(require('../assets/databases/data.db')).uri,
`${FileSystem.documentDirectory}SQLite/data.db`
);

Payload contains two or more files with the same destination path for Default.rd.xml file

I was trying to do unit testing for UWP App. When I added target application reference in Test project, the following error is giving while running the test method
Payload contains two or more files with the same destination path'Properties\Default.rd.xml'.Source files: D:\Test\MyAppTesting\Properties\Default.rd.xml D:\Test\MyApp\Properties\Default.rd.xml
No error code was given.
adding refernce
public class MyAppTesting
{
[Fact]
public async void PassingWinAppServiceTest()
{
AgendaService agendaService = new AgendaService();
var memberModel = await agendaService.GetMemberDetailsById("234");
Assert.False(String.IsNullOrEmpty(memberModel.MemberId.ToString()));
}
The only workaround I found is to remove the Default.rd.xml file from the test project.
Comments from the developer community for similar issue.
From the documentation of Runtime Directive Configuration file,
A runtime directives (.rd.xml) file is an XML configuration file that
specifies whether designated program elements are available for
reflection.
So, if reflection is not used in the test project then I believe, Default.rd.xml file can be safely removed from the test project.
After installing the NuGet, you need to add an existing project reference into the unit test project.
[right click test project -> Add -> Reference-> select an existing project}
Then check your test project dependencies, Your existing project should be there.

Connection strings not available from App.Config in Unit Tests run on TFS 2015

I'v some DB facing unit tests that take their connection string from an app.config file. I'm grabbing the strings thru ConfigurationManager class.
var conString = ConfigurationManager.ConnectionStrings["DB"].ConnectionString;
The tests run fine on dev machine but not on TFS. There is a null refernce error. If I jsut replace the connection string in unit test with a hard coded string - identical to that in app.config - then the test works. Oh yeah, and I've made sure that app.config is set to "copy to output folder".
Is there a known issue with TFS and ConfigurationManager?
pom
I recently ran into the same problem with TFS 2015 (on premises with update 2). We have multiple test projects that access a connection string from the app.config file however one particular project failed to access the connection string which caused our build to fail.
I altered the .csproj file to match other working test projects but this didn't provide any success, instead the following worked for me:
Copied the contents of the App.config to notepad
Deleted the App.config file from the project
Added a new Application Configuration File (App.config) to the project
Pasted the contents from notepad into the new App.confg file
Right click the App.config file and altered its properties:
Build Action: Content
Copy to output directory: Copy always
Upon check-in all unit tests within the project passed successfully.
It's an odd solution but it got our tests running.
Note: Deleting the App.config file was a necessary step. Changing the properties on the file (prior to deleting the file) didn't make a difference.
Update:
After applying the above solution I noticed all unit tests were running twice and after some investigation I discovered the entire issue was down to our build configuration: -
On our Visual Studio Build task we use the following parameter on our MS Build Arguments:
/p:OutDir=$(Build.StagingDirectory)
Our Visual Studio Test task was configured to look for Test Assembly in the following location:
**\$(BuildConfiguration)\*test*.dll;-:**\obj\**
Altering the Test Assembly location to the following fixed everything:
$(Build.StagingDirectory)\*test*.dll;-:**\_PublishedWebsites\**
No more issues with App.config files and unit tests ran once only.
Actually, I made another test project in my solution and added the app.config there again with the conn strings and now it works also on TFS. I don't know what the cause was but I'll leave the question here for possible reference and solution for others. Thank you.
My Test project is a separate project from the main project. Therefore it needs its own copy of App.config. Follow the steps in previous response to add new Application Configuration file and give it the same contents as in your main project.

Need to deploy a file to the MSTest shadow directory that is used in TestInitialize()

I have a unit test that deploys a database using a .bak file in the TestInitialize method. I'm running this test from mstest using the dll (not from VS) so I need the .bak file to get copied to the shadow directory that mstest creates.
I don't want to add [DeploymentItem] attributes to every test method, I'm not even sure that would work since the TestInitialize is the method that is consuming this file.
Is there a tag I can put in the project that will guarentee that the .bak file will get copied to the shadow directory when running using MSTest on the test DLL?
Thanks
See Deployment Items: http://msdn.microsoft.com/en-us/library/ms182475(v=vs.80).aspx