Upload Image to Cloud UnitTest - c#

I am trying to upload an image to a cloud and i want to be able to test this,
here is what i have tried already, I dont really understand fully what im doing, so if somebody could tell me what to do, I would appreciate it.
I have included the main method for this and the test of that method so far.
public static String UploadToCloud(string fileName)
{
try
{
SetUpConnection();
#region Upload a File from local storage to the Cloud
// Get a reference to the blob.
blob = blobContainer.GetBlobReference("Images/" + fileName.Substring(fileName.LastIndexOf('\\')));
blob.UploadFile(fileName);
return blob.Uri.ToString();
#endregion
}
catch (StorageClientException e)
{
Console.WriteLine("Storage client error encountered: " + e.Message);
return "Upload failed";
}
}
/// <summary>
///A test for UploadToCloud
///</summary>
[TestMethod()]
public void UploadToCloudTest()
{
string fileName = "https://kevin.blob.core.windows.net/cp300/Images//skin-mole.jpg";
Image expected = Image.FromFile(#"C:\Users\Public\Pictures\Sample Pictures\skin-mole.jpg");
string actual;
actual = CloudConnection.UploadToCloud(fileName);
//Compares to images and checks they are exactly the same
MemoryStream ms = new MemoryStream();
expected.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
String expectedBitmap = Convert.ToBase64String(ms.ToArray());
ms.Position = 0;
actual.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
String actualBitmap = Convert.ToBase64String(ms.ToArray());
Assert.AreEqual(expectedBitmap, actualBitmap);
//Assert.AreEqual(expected, actual);
//Assert.Inconclusive("Verify the correctness of this test method.");
}

I'd say that this isn't really a unit test -- you're trying to upload something to an external service that you have no control over and can't guarantee that the results are going to be the same from run to run.
What you've written is an integration test, which is a test of how two or more software components work together. In this case, the two components are
Your code
The cloud upload API
There's nothing wrong with integration tests, but they tend to be slower (in this case, due to uploading a file to the cloud), and they tend to be more brittle. Your integration test, for example, would break if the cloud service wasn't available. Nothing changed in your code, nothing changed in your test, but the test's results were different.
If you wanted to unit test your UploadToCloud method, I'd recommend that you start by wrapping your "cloud uploading" functionality in a class that implements an interface, e.g. ICloudUploader. Then you can mock out the pieces that actually communicate with your cloud service, and ensure that the functionality of your code is correct under all of the situations you want to test (successful upload, service is unavailable, upload fails due to file being too big, whatever).
For mocking out a class, you can either roll your own (write a class that implements your interface, for example public class FakeCloudUploader : ICloudUploader, or look into a mocking framework like Moq or RhinoMocks.
As for the test method you provided, it's not really testing the output of the method. It should validate that the string you get back from UploadToCloud is the value you expected.

Related

How to have Console mirror output from FileStream?

I want to be able to have a FileStream output to the Console for testing purposes.
[TestMethod]
public void LoggerSetStreamConsole ( ) {
logManager.WriteLine("LoggerSetStreamConsole: adding logger {0}", Name);
logger = logManager.Add(this);
Console.SetIn(new StreamReader(logger.LogStream));
logger.WriteLine("This is a test of the local logging system writing to the Console.");
logManager.WriteLine("LoggerSetStreamConsole: removing logger {0}", Name);
logManager.Remove(this);
}
logger.LogStream is a FileStream. Is this correct? Since this is running in the MSVS unit testing environment, whenever the code has Console.Write(...) there is output in the test results. That is ultimately what I am looking for.

JINT - Unable to "console.log"

I am new to JINT, and trying to just do some basic tests to kind of learn the ropes. My first attempt was to just store some javascript in my database, load it, and execute it in a unit test. So that looks essentially like this....
[Fact]
public void can_use_jint_engine() {
using (var database = DocumentStore()) {
using (var session = database.OpenSession()) {
var source = session.Load<Statistic>("statistics/1");
// join the list of strings into a single script
var script = String.Join("\n", source.Scripting);
// this will create the script
// console.log("this is a test from jint.");
//
var engine = new Jint.Engine();
// attempt to execute the script
engine.Execute(script);
}
}
}
And it doesn't work, I get this error, which makes absolutely no sense to me, and I cannot find any documentation on.
Jint.Runtime.JavaScriptExceptionconsole is not defined at
Jint.Engine.Execute(Program program) at
Jint.Engine.Execute(String source) at
SampleProject.Installers.Instanced.__testing_installer.can_use_jint_engine()
in _testing_installer.cs: line 318
Can anyone assist in shedding some light on this? I'm pretty confused at this point.
With JavaScript there are three entities - we care about. The host (browser, your application etc), the engine (JINT in this case) and the script ("console.log(...)") in this case.
JavaScript defines a bunch of functions and object as part of the language, but console is not one of them. By convention, browsers define a console object that can be used in the manner you describe. However, since your app is not a browser (and JINT does not do this by itself), there's no console object defined in your namespace (globals).
What you need to do is add a console object that will be accessible in JINT. You can find how to do this in the docs, but here's a simple example of how to add a log function to the engine so it can be used from the JS code (example taken from github).
var engine = new Engine()
.SetValue("log", new Action<object>(Console.WriteLine))
;
engine.Execute(#"
function hello() {
log('Hello World');
};
hello();
");

Killing FitNesse from within a fixture

I'm using FitNesse to do some testing with Fixtures written in C#. One of my fixtures kicks off some testing suites to run in Ab Initio in a Unix environment. I would like to be able to kill the whole test suite if one of the tests within it fail. I imagine I would need some kind of return value from the test suite (on the unix box) and then that would get passed back up to my fixture which would kill FitNesse (from within my C# fixture). This is what my KickOff() method looks like right now:
public string KickOff()
{
var data = new Dictionary<string, string>();
foreach (var row in System.IO.File.ReadAllLines(unixConfigFile))
data.Add(row.Split('=')[0], String.Join("=", row.Split('=').Skip(1).ToArray()));
string server = data["servername"];
string userId = data["username"];
string password = data["password"];
StringEncryptor3DES encryptor = new StringEncryptor3DES("fitnesse");
password = encryptor.Decrypt(password);
UnixScriptRunner runner = new UnixScriptRunner(server, userId, password, unixPath, scriptName,EtlType.AbInitio);
return runner.Run() & EtlStatus.IsEtlSuccessful(runner.LogFile,EtlType.AbInitio) ? "True":"False";
}
I think I need something that catches the value of EtlStatus.IsEtlSuccessful(), if it is false it will terminte FitNesse. The two questions I have are this:
Is this reasoning correct?
What is the code needed to terminite/kill FitNesse (or end the test suite if there is a more graceful way)?
Edit: I did a little more research and it looks like it is the 'runner' that I have to kill. Still not sure how to do this though...
If you're using Slim, you can throw an exception with "StopTest" in the class name to stop the test.
http://www.fitnesse.org/FitNesse.UserGuide.WritingAcceptanceTests.SliM.ExceptionHandling
If you're using Fit, you can throw an AbandonStoryTestExecption to stop the test.
http://fitsharp.github.io/Fit/AbandonStoryTest.html
There's a new Fit feature coming in the next release (any day now!) to throw AbandonTestSuiteException to stop the entire test suite. There's no comparable feature with Slim AFAIK.

File.Delete error "The process cannot access the file because it is being used by another process"

I have written a DotUnit test suite for testing some data import functionality in my application. It works by making a backup of some local Microsoft Access Database, let's call it 'Test.mdb', to 'Test.mdb.bak', performing some data import (and subsequent Assert checks) and then restoring the original from the backup.
The SetUp() function creates a backup if one doesn't exist.
The TearDown() function attempts to delete 'Test.mdb' and then copy 'Test.mdb.bak' to 'Test.mdb'.
Intermittently running the tests fail with this error "The process cannot access the file because it is being used by another process".
I've had a look the MSDN on File.Delete and IO permissions but couldn't find what I was after. Does anyone know if there is a .NET feature that will allow me to completely lock the file before attempting to delete it? Or find which process is accessing it at the time of deletion?
I had a similar issue while unit testing Entity Framework code using a SQLite database where each test needed to use a fresh instance of a database, so my the [TestCleanup] method was doing a File.Delete on the database, but was getting the same "used by another process" error.
Before I called, File.Delete, I had to add the following to fix my issue.
GC.Collect();
GC.WaitForPendingFinalizers();
[TestInitialize]
public void MyTestInitialize()
{
// Copies the embedded resource 'MyDatabase.db' to the Testing Directory
CommonTestFixture.UnpackFile("MyDatabase.db", this.GetType(), this.TestContext.TestDeploymentDir);
}
[TestCleanup]
public void MyTestCleanup()
{
// Adding the following two lines of code fixed the issue
GC.Collect();
GC.WaitForPendingFinalizers();
// Removes 'MyDatabase.db' from the testing directory.
File.Delete(Path.Combine(this.TestContext.TestDeploymentDir, "MyDatabase.db"));
}
[TestMethod]
public void GetVenueTest()
{
// CreateTestEntities() is a helper that initializes my entity framework DbContext
// with the correct connection string for the testing database.
using (var entityFrameworkContext = CreateTestEntities())
{
// Do whatever testing you want here:
bool result = entityFrameworkContext.TestSomething()
Assert.IsTrue(result);
}
}
You might reconsider your testing approach. Instead:
Create a temporary copy of the file
Perform the actions that are being tested on the temp file
Release all handles (close all connections) to the temp file
Delete the temp file
Using this pattern, the only process that will be accessing the file will be the thread running the unit test.
Use the function: System.IO.Path.GetTempFileName();
http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename.aspx
EDIT: Here is one way to code it:
var tempFile = System.IO.Path.GetTempFileName();
System.IO.File.Copy(#"C:\Test.mdb", tempFile, true);
// 2. Test tempFile
// 3. Release handles to tempFile, use a using statement around any
// streams or System.IO API's that are using the file in any way.
System.IO.File.Delete(tempFile);
These two lines solve the issue.
GC.Collect();
GC.WaitForPendingFinalizers();
I have tested this in my code and it worked well.
--- Jeetendra

VS2008: File creation fails randomly in unit testing?

I'm working on implementing a reasonably simple XML serializer/deserializer (log file parser) application in C# .NET with VS 2008. I have about 50 unit tests right now for various parts of the code (mostly for the various serialization operations), and some of them seem to be failing mostly at random when they deal with file I/O.
The way the tests are structured is that in the test setup method, I create a new empty file at a certain predetermined location, and close the stream I get back. Then I run some basic tests on the file (varying by what exactly is under test). In the cleanup method, I delete the file again.
A large portion (usually 30 or more, though the number varies run to run) of my unit tests will fail at the initialize method, claiming they can't access the file I'm trying to create. I can't pin down the exact reason, since a test that will work one run fails the next; they all succeed when run individually.
What's the problem here? Why can't I access this file across multiple unit tests?
Relevant methods for a unit test that will fail some of the time:
[TestInitialize()]
public void LogFileTestInitialize()
{
this.testFolder =
System.Environment.GetFolderPath(
System.Environment.SpecialFolder.LocalApplicationData
);
this.testPath = this.testFolder + "\\empty.lfp";
System.IO.File.Create(this.testPath).Close();
}
[TestMethod()]
public void LogFileConstructorTest()
{
string filePath = this.testPath;
LogFile target = new LogFile(filePath);
Assert.AreNotEqual(null, target);
Assert.AreEqual(this.testPath, target.filePath);
Assert.AreEqual("empty.lfp", target.fileName);
Assert.AreEqual(this.testFolder + "\\empty.lfp.lfpdat", target.metaPath);
}
[TestCleanup()]
public void LogFileTestCleanup()
{
System.IO.File.Delete(this.testPath);
}
And the LogFile() constructor:
public LogFile(String filePath)
{
this.entries = new List<Entry>();
this.filePath = filePath;
this.metaPath = filePath + ".lfpdat";
this.fileName = filePath.Substring(filePath.LastIndexOf("\\") + 1);
}
The precise error message:
Initialization method
LogFileParserTester.LogFileTest.LogFileTestInitialize
threw exception.
System.IO.IOException:
System.IO.IOException: The process
cannot access the file
'C:\Users\<user>\AppData\Local\empty.lfp'
because it is being used by another
process..
You should be mocking the file system access, and not actually reading/writing files in your unit tests.
Sounds like some of the tests are being run at the same time. Do the individual tests write to the file, or just read it? If they're read only, I'm sure we can make a minor change to enable them to run concurrently. More details?

Categories