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.
Related
I have a service that runs as a console app and outputs to stdout and stderr streams to the console. The developers don't want to add any logging capabilities since it was mainly designed for linux world and they have tools like logroate and other means already but don't care about the windows port. I want to redirect those streams into a log and I'm able to do it like this:
service.exe 2>&1 >> service.log
But if I leave this running this log will grow out of control. So I tried using something called logrotateWin but it needs to rename the log file and I get access denied since its in use. So I'm trying to write another app that can write to logfile and rotate it based once a day and only keep last n logs.
I want to be able to run it like:
service.exe 2>&1 | logrotater.exe
So I'm trying to write logrotater with the following code but it seems to fail to read the stream from the pipeline. It can read the stream if it stops like from a simple echo "test" command source, but not from service.exe that continuously keeps streaming data out. Any suggestions?
So this works:
echo "test" | logrotater.exe
But this doesn't work:
service.exe 2>&1 | logrotater.exe
static void Main(string[] args) {
Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); // This will allow input >256 chars
while (Console.In.Peek() != -1) {
string input = Console.In.ReadLine();
Console.WriteLine("Data read was " + input);
}
}
Add a Log() method that opens and closes the file as needed. Moving to a separate method will make it easier to isolate these changes from the rest of the program. One easy way to open/close as needed is with File.AppendAllText().
static void Main(string[] args)
{
Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); // This will allow input >256 chars
string input;
while ( (input= Console.ReadLine()) != null)
{
Log(input);
}
}
static void Log(string data)
{
string msg = $"Data read was {data}";
Console.WriteLine(msg);
File.AppendAllText("C:\YourPath", msg);
}
I have a very simple TestEventListener that send output to the console and to a text file. However, it currently prints everything and I only want to capture the event, but I'm not sure how to do it. Also, is it possible to get it as it happened? As of right now it only seems to be printing after the test is run which isn't really ideal. Here's what I have now:
class TestListener : ITestEventListener
{
StreamWriter _outputStream;
string _outputFile;
public TestListener(string outputPath)
{
_outputFile = outputPath + "\\ConsoleLog.txt";
_outputStream = new StreamWriter(_outputFile);
}
public void OnTestEvent (string report)
{
WriteText(report);
}
public void WriteText(string text)
{
Console.WriteLine(text);
_outputStream.WriteLine(text);
}
}
It's your code that's printing everything. The report, as you have seen, is XML. It's up to you to look at it in your code and decide what to print.
Most likely, in the events you receive, you will see test starts, test results and immediate text output if you have any. Which of those do you want to display?
As far as only getting output after the test finishes, that would be the test result output, which obviously has to come after the end of the test. It includes an element output with any text writes that were done in the course of the test.
If you want immediate output, which comes as a test-output report, you have to create it in your tests. The only output that is sent this way is Console.Error, TestContext.Error and TestContext.Progress. This is the only output that comes to you before the end of the test.
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.
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
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?