I am very new to CodedUI test automation framework. I came across TestContext which has the important information regarding test result outputs and directories.
Actually i have created a static Logger class which writes output data to a .txt file. Now i want to create it under TestResults folder. Everytime i am running the test method it is creating a folder followed by some timestamp. I want to create my Results.txt file in that location.
Below is the code i am using :
public static class Logger
{
string logLocation = TestContext.TestDeploymentDir + "\\Results.txt";
static Logger() {
File.Create(logLocation);
using (var fs = new FileStream(logLocation, FileMode.Truncate))
{
}
}
public static void ResultLog(int testcasenum,String Expected,String Actual, String textResult)
{
FileInfo outtxt = new FileInfo(logLocation);
StreamWriter logline = outtxt.AppendText();
logline.WriteLine("Test Case : " + testcasenum);
logline.WriteLine("{0},{1},{2}", "Expected - "+Expected, "Actual - "+Actual, "Result - "+textResult);
// flush and close file.
logline.Flush(); logline.Close();
}
}
Now i am getting a compile time error saying A field initializer cannot reference the non-static field, method, or property TestContext.TestDeploymentDir. Not sure how to resolve this error or whether it is possible or not ?
You're going to need to mark logLocation as static since it is contained in a static class. It's kind of silly but all members of a static class do also need to be marked static. I believe this is to prevent confusion when reading larger classes where you cannot see the class declaration. Next your current error message also says TestContext.TestDeploymentDir is not marked static and you'll need to modify that as well if possible. If not you'll need to implement a singleton pattern to provide a static copy of an instance of that class. Depending on the way that class works it may or may not be possible.
Finally figured out a way to get the out path of Coded UI framework. Below is the code i have written :
public static class Logger
{
static string uripath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\Results.txt";
public static string logLocation = new Uri(uripath).LocalPath;
static Logger() {
using (File.Create(logLocation))
{ }
using (var fs = new FileStream(logLocation, FileMode.Truncate)){}
}
public static void ResultLog(int testcasenum,String Expected,String Actual, String textResult)
{
FileInfo outtxt = new FileInfo(logLocation);
StreamWriter logline = outtxt.AppendText();
logline.WriteLine("Test Case : " + testcasenum);
logline.WriteLine("{0},{1},{2}", "Expected - "+Expected, "Actual - "+Actual, "Result - "+textResult);
// flush and close file.
logline.Flush(); logline.Close();
}
}
uripath will contain the same path as that of TestContext.TestDeploymentDir. Now Results.txt will come as an attachment in Test Explorer and we can see the output.
Related
I need a very simple to imagine thing - modify System.Console class method WriteLine to write not only in console, but also in text log file.
I simply need to run this function with preset arguments prior to any call to WriteLine and then do generic WriteLine:
class Logger
{
static public void WriteLog(string logMessage, string fileName ,bool addTimeStamp = true)
{
//Getting temp folder
string destPath = Path.GetTempPath();
//Creating folder
if (!Directory.Exists(destPath))
Directory.CreateDirectory(destPath);
//Naming log file
var filePath = String.Format("{0}\\{1}.log",
destPath,
fileName
);
//Writing to timestamp
if (addTimeStamp)
{
logMessage = String.Format("[{0}] - {1}{2}",
DateTime.Now.ToString("HH:mm:ss", CultureInfo.CurrentCulture),
logMessage,
Environment.NewLine);
}
else
{
logMessage = String.Format("{0}{1}",
logMessage,
Environment.NewLine);
}
//Writing to log
File.AppendAllText(filePath, logMessage);
}
}
I thought about inheritance, but I cannot even create a class since "Static class ConsoleX cannot derive from type Console. Static classes must derive from object".
Is there at all simple way to wrap around WriteLine method? I would do a separate (not inherited) class for it but then I need to create like 18 overloads for this method just to pass through arguments to 18 overloads of generic WriteLine, so it feels like waste of effort for seemingly simple thing.
Console.WriteLine is equivalent to Console.Out.WriteLine, so you can implement your own TextWriter and pass it to Console.SetOut to achieve your purpose.
BTW a class can not inherit a static class in any way.
class ConsoleOut : TextWriter
{
private TextWriter _oldOut = Console.Out;
// This overload method is the base method of all
// Write or WriteLine overloads.
// But you can override other methods as you want
public override void Write(char[] buffer, int index, int count)
{
// Write to the original console
_oldOut.Write(buffer, index, count);
// Write to file
Logger.Write(buffer, index, count);
}
}
Console.SetOut(new ConsoleOut());
BTW 2, the default console ouput is synchronized, but your method isn't, this is what you need to consider, because you may get IOException.
It is not possible to create a derived class from a static class in C#. A static class is a class that cannot be instantiated and therefore cannot be inherited from. Instead, you can use a regular class or an abstract class as a base for a derived class.
In my C# application I have a getLogFile which is set by calling the GetLogFile() method:
private static string getLogFile = GetLogFile();
private static string GetLogFile()
{
var fileTarget = (FileTarget)LogManager.Configuration.FindTargetByName("file-target");
var logEventInfo = new LogEventInfo();
string fileName = fileTarget.FileName.Render(logEventInfo);
if (!File.Exists(fileName))
throw new Exception("Log file does not exist.");
return fileName;
}
I'm now trying to unit test some code which will require the getLogFile variable to be set. I'd like to mock this in some way as I'd like to use specific log data for my test but am not sure how to go about it. How can I do this?
"Mocking" a private static field or method is not really possible.
To have this kind of method as a private member of another class smells like a violation of Single Responsibility Principle.
You should probably refactor this behavior to a separate class and hide it behind an interface. I'm not entirely sure what the NLog Code does, but what your method really seem to do is not providing the log file, but the name of the log file (you return fileName) So this is how it could look like:
public interface ILogFileNameProvider
{
string GetLogFileName();
}
public class DefaultLogFileNameProvider : ILogFileNameProvider
{
public string GetLogFileName()
{
// your code ommitted
}
}
It's just an example on how you can handle it. The naming/structure and how you use it is up to you.
This interface can then be injected in the using class that currently has the private methods. This dependency/call can be mocked.
Usage with constructor injection:
public class LogFileNameUsingService
{
private readonly ILogFileNameProvider _logFileNameProvider;
public LogFileNameUsingService(ILogFileNameProvider logFileNameProvider)
{
_logFileNameProvider = logFileNameProvider;
}
}
Test with xUnit and AutoMocker as example:
[Theory]
public void TestWithMockedLogFileName()
{
//Arrange
var mocker = new AutoMocker();
var logFileNameProviderMock = mocker.GetMock<ILogFileNameProvider>();
logFileNameProviderMock.Setup(x => x.GetLogFileName()).Returns("your mocked file name.log");
var sut = mocker.CreateInstance<LogFileNameUsingService>();
//Act
var result = sut.TestedMethodWhichUsesLogFileName();
//Assert whatever you want to test
}
This also allows you swap out the current logic to get a log file later without changing the logic of the existing class.
I have below code with error. Error message is very simple but I cant get its sense. To me looks like fileStream is being initalized when it is reading data. Can you please guide what I m missing ?
class Program
{
Stream fileStream=null;
static void Main(string[] args)
{
}
private static void ReadData()
{
using (System.Net.WebResponse tmpRes = ftpReq.GetResponse())
{
fileStream = tmpRes.GetResponseStream();
}
}
EDIT:
I have simplified this code and removed few parts. Error is on fileStream = tmpRes.GetResponseStream();
You are referencing a member variable within a static method. A member variable requires an instance of the class to be referenced where as a static method does not and can be shared across instances of the class.
Change
Stream fileStream=null;
to
static Stream fileStream=null;
I am trying to access variables from a static Method. I understand the basic concept of static vs non static methods, but still do not fully understand what a static method can and cannot access.
At first I tried to put my variables at the top in the Program Class as you can see from some of my commented out lines. I could not access them from my static method which as I learned more about static made sense. But then I put the variables inside the static method. And this is what I do not understand. Inside the static method I can set fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); yet once outside the if statement the sw = new StreamWriter(fs) gave me an error when I had FileStream fs inside the static method. Tried making it static as you can see by the commented out line inside the static method but that does not work either. The only way I seem to be able to access my variables is if I make them static inside the Program class (outside the static method).
class Program {
static FileStream fs;
// public bool fileopen = false;
// String filename = #"D:\Stock Trading\Test1.txt";
static void Main(string[] args) {
CreateDebugFile();
}
public static void CreateDebugFile() {
StreamWriter sw;
bool fileopen = false;
// static FileStream fs;
String filename = #
"D:\Stock Trading\Test1.txt";
if (!fileopen) {
fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
fileopen = true;
}
sw = new StreamWriter(fs);
sw.Write("Current Bar" + "\t" + "time" + "\t" + "Open" + "\t" + "Close" + "\t" + "Low" + "\t" + "High");
}
}
the static keyword from MSDN:
A non-static class can contain static methods, fields, properties, or events. The static member is callable on a class even when no instance of the class has been created. The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created. Static methods and properties cannot access non-static fields and events in their containing type, and they cannot access an instance variable of any object unless it is explicitly passed in a method parameter.
It is more typical to declare a non-static class with some static members, than to declare an entire class as static. Two common uses of static fields are to keep a count of the number of objects that have been instantiated, or to store a value that must be shared among all instances.
Static methods can be overloaded but not overridden, because they belong to the class, and not to any instance of the class.
Although a field cannot be declared as static const, a const field is essentially static in its behavior. It belongs to the type, not to instances of the type. Therefore, const fields can be accessed by using the same ClassName.MemberName notation that is used for static fields. No object instance is required.
C# does not support static local variables (variables that are declared in method scope).
Static means that it can be accessed directly against an object without creating an instance, i.e a class, so a static member Name defined in class MyClassName can be accessed like so: MyClassName.Name(instead of new MyClassName().Name), and when you access a static member from inside that class, you can just use Name but the compiler is treating similar to you would be accessing it from outside the class.
While a static value is unchanged, any people who call that static property in an application are accessing the same instance, which can lead to concurrency issues if the value can be changed from outside the class.
Take the following example:
public class MyClassName
{
public static string FilePath = #"C:\Temp";
public static FileStream fs;
public static void CreateFileStream()
{
//creates a file stream
}
}
If two people call the same method at the same time, MyClassName.CreateFileStream() then the one who gets in there first creates a file stream and sets it to fs, then the second person creates a file stream and sets it to fs, now it is possible that someone has a reference to the file stream in the class, and the other one could be holding on to a reference to the original file stream that is no longer set on the class MyClassName.
As such you will want to pay mind to how you expose static members (not an issue in your specific example, but important to keep in mind). If you declare a static field, you should be sure to instantiate it or keep it private to the class so you can be sure it is instantiated be for using it.
In your case you are creating a new file stream every time you call that method because your bool fileopen is inside the method, anything inside of a method is only available inside that method, regardless of being static or not, and is created again every time that method is called, and you need to use the static keyword on every declaration of a field or property or method that you want to call from another static field, property, or method.
class Program {
static FileStream fs; //needs to be static
public static bool fileopen = false; //needs to be static
static String filename = #"D:\Stock Trading\Test1.txt";
//needs to be static, or this one could also be
//const if it will never change
static void Main(string[] args) {
CreateDebugFile();
}
public static void CreateDebugFile() {
//...
}
}
1. I could not access them from my static method
Static method can not use instance variable. It can only use local variable (declared inside variable) and static variable of that class or another class.
so
public static bool fileopen = false;
static String filename = #"D:\Stock Trading\Test1.txt";
would work
2. yet once outside the if statement the sw = new StreamWriter(fs) gave me an error
That's because you have not initialized the variable fs. you must initialized it before you use.
public static void CreateDebugFile() {
StreamWriter sw = null; //would remove compile time error but beware of null reference exception :)
bool fileopen = false;
String filename = #
"D:\Stock Trading\Test1.txt";
if (!fileopen) {
fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
fileopen = true;
}
sw = new StreamWriter(fs);
sw.Write("Current Bar" + "\t" + "time" + "\t" + "Open" + "\t" + "Close" + "\t" + "Low" + "\t" + "High");
}
statict classes and Methods can only access and calll to statict variables.
static FileStream fs;
/*
you can't access to this variables from a static method,
because they are declare as instance variable, even when they are nested in the same class
*/
// public bool fileopen = false;
// String filename = #"D:\Stock Trading\Test1.txt";
//you need to add the word static at begin of declaration
public static bool fileopen = false;
static string filename = #"D:\Stock Trading\Test1.txt";
Consider that static classes and variables will be alive until the program finish instead a normal class all objects will be destroyed after they use or program finish
I'm making my first "real" C# program and I'm thinking about where I should define error messages? Should I do something like this:
static class Error
{
public static string Example { get { return "Example Error"; } }
}
I could also use values here instead of properties but that would still mean I can't do something like this:
public static string FailedToParse(string filepath, string exmessage)
{
return ("Failed to parse " + filepath + ".\n" + exmessage);
}
So, is that a good idea? Should I make a new class and write a method for each error? How do you guys implement this and why?
I already read
In C#, what's the best way to store a group of constants that my program uses?
The right way to use Globals Constants
I think this is something everything should figure out by themselves.
One like to display nice messages to users another just throw those default generated ones.
Personally I like to have codes for errors.
Something like this:
I create a static class called ExceptionFactory and just pass the code to the method called RaiseException.
public static class ExceptionRegions
{
public static int Internet = 0xA;
public static int FileSystem = 0xB;
}
public class InternetConnectionException : Exception
{
public InternetConnectionException () : base("No internet connection available") { }
}
public class FileSystemAccessException : Exception
{
public FileSystemAccessException () : base("Access to specified path caused an error") { }
}
public static class ExceptionFactory
{
public static void RaiseException(int code)
{
switch(code)
{
case ExceptionRegions.Internet : throw new InternetConnectionException();
...
...
}
}
}
Btw, this is a well known pattern called Factory Pattern. :)
Why I like this, because it allows me to set regions in my application.
Usually an application has many interfaces such as file system, or web services, or database and all I need to do is create a code for each area and the factory will throw a nice message to user without exposing to the user name of database and number of code line or whatever the default generated error message looks alike.