C#- Print an additional message to the the actual specflow error - c#

I'm trying to add an additional message to the the actual specflow error message using the AfterStep hook as below but it is not working, can someone please suggest a better way.
[AfterStep]
public void AfterStep()
{
if (this.scenarioContext.ScenarioExecutionStatus == ScenarioExecutionStatus.TestError)
{
var stepName = this.scenarioContext.StepContext.StepInfo.Text;
var stepTable = this.scenarioContext.StepContext.StepInfo.Table;
var errorLength = this.scenarioContext.TestError.Message.Length;
this.scenarioContext.TestError.Message.Insert(errorLength, "\r\n Failed at Step: " + stepName + "\r\n" + stepTable + "\r\n");
}
}
I have tried to throw another custom exception for printing my the additional message from inside the AfterStep hook but that changes the original stack trace.

This answer is not exactly what you're asking, but I hope it gets to the spirit of what you're trying to achieve.
My preferred practice in this scenario -- wanting to add more context about failures -- is to use the SpecFlow Output API.
The instructions in long-form are at the link above, but you can inject ISpecFlowOutputHelper into your step definitions classes. This will then allow you to write additional lines in your SpecFlow output at a given step.
Typically, I'll use a try/catch statement to catch an exception that happens during step execution, then I'll use ISpecFlowOutputHelper's WriteLine method to print some additional information.
This allows you to print the context in the step where it happens, which I find is useful when reviewing failed scenarios.

I implemented this to fix it. This prints the message I wanted to print and also shows the actual stack trace.
[AfterStep]
public void AfterStep()
{
if (this.scenarioContext.ScenarioExecutionStatus == ScenarioExecutionStatus.TestError)
{
var errorMessage = this.scenarioContext.TestError.Message;
var stepName = this.scenarioContext.StepContext.StepInfo.Text;
var stepTable = this.scenarioContext.StepContext.StepInfo.Table;
var exception = this.scenarioContext.TestError.GetBaseException();
exception.GetType().GetField("_message", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(exception, "Failed at Step: \r\n" + stepName + "\r\n" + stepTable + "\r\n Actual Error: \r\n" + errorMessage);
var ex = ExceptionDispatchInfo.Capture(exception);
ex.Throw();
}
}

Related

handle error on Microsoft.AnalysisServices update method

I am updating dimension definition in 'Data Source View'. Doing it using C# code inside SSIS script task.
Here is simplified C# code:
DataSourceView ASDataSourceView;
//DataSourceView inherits from MajorObject
ASDataSourceView.Schema.Tables["DimTable"].ExtendedProperties["QueryDefinition"] = "SELECT * FROM ufc.TableWithData";
ASDataSourceView.Update();
I need to handle error which may appear during Update() method.
I thought that usual approach with try catch will work but it seems it is not a case.
I need to get an xml response object somehow and then check if it is empty(no error) or parse it and build further logic.
I was trying to read Microsoft documentation but have no idea how to do it.
XmlaWarningCollection Class
When I run update xml statement in SSMS I get the following messages:
when update succeed:
<return xmlns="urn:schemas-microsoft-com:xml-analysis">
<root xmlns="urn:schemas-microsoft-com:xml-analysis:empty" />
</return>
when update fails(fails because of syntax error not logic which is also not very correct from simulation point of view):
XML parsing failed at line 9597, column 63: The name in the end tag of the element must match the element type in the start tag.
Run complete
Can anybody help?
I think I finally found solution:
First you need to enable CaptureXML option;
ServerName.CaptureXml = true;
Second run Update with XmlaResultCollection option:
UpdateOptions uo = default(UpdateOptions);
UpdateMode om = default(UpdateMode);
XmlaWarningCollection xm = null;
ASDataSourceView.Update(uo, om, xm);
Third you execute update statement:
XmlaResultCollection resultCollection = ServerName.ExecuteCaptureLog(false, false);
After that I was able to parse resultCollection object:
String ErrorMessages = String.Empty;
if (resultCollection.ContainsErrors) {
ErrorMessages += $"Errors occured in cube {ConnectionString.CatalogName}:" + Environment.NewLine;
foreach (AS.XmlaResult result in resultCol) {
foreach (object error in result.Messages) {
if (error.GetType() == typeof(AS.XmlaError))
ErrorMessages += "ERR: " + ((AS.XmlaError)error).Description + Environment.NewLine;
else if (error.GetType() == typeof(AS.XmlaWarning))
ErrorMessages += "WARN: " + ((AS.XmlaWarning)error).Description + Environment.NewLine;
}
}
throw new Exception(ErrorMessages);
}

How does the Shouldly assertion library know the expression the assertion was applied to?

The Shouldly assertion library for .NET somehow knows what expression the assertion method was called on so it is able to display it into the message. I tried to find out how it works but got lost in the source code. I suspect it looks into the compiled code but I would really like to see how this happens. From the documentation
map.IndexOfValue("boo").ShouldBe(2); // -> map.IndexOfValue("boo") should be 2 but was 1
Somehow Shouldly knows the expression map.IndexOfValue("boo") and was able to display it in the test failure message. Does anyone know how this happens?
Looking at the code, that's pretty smart.
The magic is happening in the ActualCodeTextGetter class. First, it retrieves the line of the source code file by using the StackTrace:
StackTrace stackTrace = trace ?? new StackTrace(true);
// Cut for brevity
StackFrame stackFrame = frame;
this.ShouldlyFrameIndex = index - 1;
string fileName = stackFrame.GetFileName();
this._determinedOriginatingFrame = fileName != null && File.Exists(fileName);
this._shouldMethod = this.ShouldlyFrame.GetMethod().Name;
this.FileName = fileName;
this.LineNumber = stackFrame.GetFileLineNumber() - 1;
Once it has the name of the source code file, along with the line and offset of the statement, it's just a matter of reading directly the file:
private string GetCodePart()
{
string str = "Shouldly uses your source code to generate its great error messages, build your test project with full debug information to get better error messages\nThe provided expression";
if (this._determinedOriginatingFrame)
{
string codeLines = string.Join("\n", ((IEnumerable<string>) File.ReadAllLines(this.FileName)).Skip<string>(this.LineNumber).ToArray<string>());
int indexOfMethod = codeLines.IndexOf(this._shouldMethod);
if (indexOfMethod > 0)
str = codeLines.Substring(0, indexOfMethod - 1).Trim();
str = !str.EndsWith("Should") ? str.RemoveVariableAssignment().RemoveBlock() : this.GetCodePartFromParameter(indexOfMethod, codeLines, str);
}
return str;
}
There's a lot more logic going on to isolate precisely the statement, but in short the trick is:
Use the StackTrace to retrieve the location of the source code and the line of the statement
Parse the source code to retrieve the exact statement
Of course, it can work only if you're running it on the same machine you used to compile the code.
It does it by parsing the stack trace for the current call stack until it finds a method that is not internal to Shouldly and treats its name as the name of the method under test.

can't get the body/attachments of new mails in outlook

I've developed an Outlook plugin using C# where for each new mail received, i get(and save) the sender/subject/the body of email & the attachments. Well, the last 2 gave me a headache. I can see the sender and the subject of the new mail but for the body&attachments it seems that is a problem. I've used NewMailEx for getting the new mails in Inbox. The function looks like this:
private void Application_NewMailEx(string EntryIDCollection)
{
string[] entryIdArray = EntryIDCollection.Split(',');
foreach (string entryId in entryIdArray)
{
try
{
Outlook.MailItem item = (Outlook.MailItem)Application.Session.GetItemFromID(EntryIDCollection, null);
string subj = item.Subject; //works
string to = item.To; //works
string bec = item.BCC; //does not work but dont care
string body = item.Body; //DOES NOT SAVE THE BODY OF THE NEW MAIL RECEIVED
string final = "Sender: " + item.SenderEmailAddress + "\r\n" + "Subject: " + subj + "\r\n" + "BCC: " + bec + "\r\n" + "TO: " + to + "\r\n\n" + "Body: " + body + "\r\n\n";
System.IO.File.AppendAllText(#"D:\tmp\atr.txt", final);
//the result of item.attachments.count is always 0 , even though I've
//sent mails with a different number of attachments. So the if
//statement is false
if (item.Attachments.Count > 0)
{
for (int i = 1; i <= item.Attachments.Count; i++)
{
item.Attachments[i].SaveAsFile(#"D:\tmp\" + item.Attachments[i].FileName);
}
}
Marshal.ReleaseComObject(item);
}
catch (System.Exception e)
{
MessageBox.Show(e.Message);
}
}
}
Where does the Item variable come from? You need to initialize it using Application.Session.getItemfromID().
I'm writing in VBA, so I feel like posting my code here would be a faux pas, but I have come to a solution using similar Object Libraries from the Outlook application that I think transfer well to your C++ intentions.
First of all, switching to POP3 certainly fixes this problem, but you're stuck using POP3, which is only ideal from a programming standpoint.
The solution I have found follows this algorithm:
//Generate Outlook MailItem Object, "item"
//If item.DownloadState is not 1,
//item.Display
//item.Close(1)
//Perform end of code operations
//Call Function that is identical to Application_NewMailEx but is not Application_NewMailEx because Application_NewMailEx is a function that is thrown during the incoming mail event.
//Else,
//Perform Intended Code
You see how calling a function identical to Application_NewMailEx creates a kind of loop because if item.DownloadState is not 1, you'll be calling that function again? I get that this isn't the most ideal coding practice, but I have scoured the internet and Outlook Application and Outlook Object Library experts have no idea how to solve this problem any other way (in fact, no one even proposes THIS solution)
For my full VBA Solution Check out:
https://superuser.com/questions/894972/outlook-strange-item-attachments-error/990968#990968

JScript runtime error in Sharepoint Webpart

I'm trying to design a webpart that looks at a list of news items, and initially prints all the rows in order by date. If the user selects a type of news item, then only those news items will be displayed (again, in order by date). The problem is that my webpart keeps throwing up this error when I try to debug it:
Microsoft JScript runtime error: Unknown runtime error
And this mess pops up behind it:
RTE.RteUtility.$1n = function($p0, $p1) {
if (RTE.RteUtility.isInternetExplorer() && $p0.tagName === 'TABLE') {
var $v_0 = document.createElement('DIV');
$v_0.innerHTML = '<table>' + $p1 + '</table>';
while ($p0.childNodes.length > 0) {
$p0.removeChild($p0.childNodes[0]);
}
RTE.RteUtility.$1E($v_0.firstChild, $p0);
}
else {
$p0.innerHTML = '<div>RTE</div>' + $p1;
$p0.removeChild($p0.firstChild);
}
}
The line: "$p0.innerHTML = 'RTE' + $p1" seems to be causing the problem. Well, otherwise, that's a really specific error message, thanks Microsoft. :/
The error seems to happen after CreateChildControls is called by NewsFeed.cs. My best theory right now is maybe something in NewsFeedUserControl.ascx.cs is causing an error, but as I'm a total neophyte at SharePoint I have no idea what that could possibly be. Is it because of this code in Page_Load?
protected void Page_Load(object sender, EventArgs e)
{
list = web.Lists["NewsFeedLI"];
query.Query = "<Where><IsNotNull><FieldRef Name='Headline' /></IsNotNull></Where></Query>" +
"<OrderBy<FieldRef Name='Article_x0020_Date' Ascending='True' /></OrderBy>";
SPListItemCollection result = list.GetItems(query);
foreach (SPListItem item in result)
{
newsList.Text = newsList.Text + item["Headline"].ToString() + Environment.NewLine;
newsList.Text = newsList.Text + item["Summary"].ToString() + Environment.NewLine + Environment.NewLine;
}
}
See, I don't know.
Try predefining the text that you return in your loop. If the web part looks OK with basic text (e.g. "Hello World") but not with more advanced values then that it where your problem lies.
You will want to ensure that you apply the appropriate encoding to any output you are rendering to the screen as this may be causing you issues.

Debugging: Microsoft JScript runtime error

I am desperately in need of debugging help, been stuck at this error for 6 days now.....
the error I get in my ASp.net app is :
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near '<script type='text/j'.
Below is the relevant code snippet,
CollyDataExchangeWebService Col_ValSub = new CollyDataExchangeWebService();
CollyReportServiceRequest ServiceReq = new CollyReportServiceRequest();
CollyReportServiceRequestData ServiceReqData = new CollyReportServiceRequestData();
ServiceReqData.AmendmentIndicatorSpecified = true;
ServiceReqData.AmendmentIndicator = false;
ServiceReqData.CollyReport = ColRep;
ServiceReq.ServiceRequestData = ServiceReqData;
ServiceReq.ServiceRequestHeader = ServiceHeader;
errValidate = null;
//btnOK.OnClientClick = "MSGShow()";
bool Valid = true;
string ErrMsgs = "";
if (((System.Web.UI.WebControls.Button)(sender)).CommandArgument == "Validate")
{
CollyReportServiceResponse ValResponse = Col_ValSub.validateReport(ServiceReq);
switch (ValResponse.ServiceResponseHeader.ServiceStatus)
{
case ServiceStatus.Successful:
btnOK.OnClientClick = "";
valHeader.Text = "Validation is Completed. No errors were found";
mlValPopup.Show();
break;
case ServiceStatus.ValidationErrors:
Valid = false;
ErrMsgs = ErrMsgs + _ValidationError(ValResponse);
ValBTN.Update();
mlValPopup.Show();
break;
case ServiceStatus.SystemError:
btnOK.OnClientClick = "";
Valid = false;
ErrMsgs = ErrMsgs + _SystemError(ValResponse);
ValBTN.Update();
mlValPopup.Show();
break;
}
After hours of debugging I found this line to be causing the error:
CollyReportServiceResponse ValResponse = Col_ValSub.validateReport(ServiceReq);
After 6 days of debugging and frustration I found that SOME records cause this issue and others dont in OLDER versions of the code but in new version ALL of the records lead to this error so it has to do something with the data in the DB which means SOME method in the code behaves differently to nulls but I cant find out exactly what the issue is because my app is 30k lines of code
after searching around and trying various solutions, the below 2 are not the solutions to my issue.
forums.asp.net/t/1357862.aspx
http://www.vbforums.com/showthread.php?t=656246
I want to mention that I am already having a difficult time dealing with this application because it was written by other programmers that are now long gone leaving behind non-documented or commented spaghetti code.
I did not code this but other programmers from past have put Response.Write in code:
private void MessageBox(string msg)
{
if (!string.IsNullOrEmpty(msg))
{
Global.tmpmsg = msg;
msg = null;
}
Response.Write("<script type=\"text/javascript\" language=\"javascript\">");
Response.Write("window.open('ErrorPage.aspx?msg=" + "','PopUp','screenX=0,screenY=0,width=700,height=340,resizable=1,status=no,scrollbars=yes,toolbars=no');");
Response.Write("</script>");
}
This one is in another method:
Response.Write("<script type=\"text/javascript\" language=\"javascript\">");
Response.Write("alert('No search resuls were found');");
Response.Write("</script>");
Or This:
if (!string.IsNullOrEmpty(msg))
{
Global.tmpmsg = msg;
Response.Write("<script type=\"text/javascript\" language=\"javascript\">");
Response.Write("window.open('ErrorPage.aspx?msg=" + "','PopUp','screenX=0,screenY=0,width=700,height=340,resizable=1,status=no,scrollbars=yes,toolbars=no');");
Response.Write("</script>");
}
After Jrummel`s comment I added this to code and then nothing at all happened.
private void MessageBox(string msg)
{/*
if (!string.IsNullOrEmpty(msg))
{
Global.tmpmsg = msg;
msg = null;
}
Response.Write("<script type=\"text/javascript\" language=\"javascript\">");
Response.Write("window.open('ErrorPage.aspx?msg=" + "','PopUp','screenX=0,screenY=0,width=700,height=340,resizable=1,status=no,scrollbars=yes,toolbars=no');");
Response.Write("</script>");
*/
// Define the name and type of the client scripts on the page.
String csname1 = "PopupScript";
Type cstype = this.GetType();
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Check to see if the startup script is already registered.
if (!cs.IsStartupScriptRegistered(cstype, csname1))
{
String cstext1 = "<script type=\"text/javascript\" language=\"javascript\">" + " " + "window.open('ErrorPage.aspx?msg=" + "','PopUp','screenX=0,screenY=0,width=700,height=340,resizable=1,status=no,scrollbars=yes,toolbars=no');" + " " + "</script>";
cs.RegisterStartupScript(cstype, csname1, cstext1, false);
}
}
I have found the error after 2 weeks of debugging and 2 days of Brute Forcing:
In one of the 800 DB columns that I have there was a null/improper value. This value reacted with one of the 150 methods in my ASP.NET code in such a way as to present a JavaScript error even though Response.Write() was NOT the issue. I have not found which method it was that reacted to this value but I have found the solution which is to simply input a valid value on the column record..
How a programmer can brute force to find the issue:
In my case after long days of debugging I took a sample of one working record and another sample of an error leading record. Once I had achieved this, I used
DELETE FROM tablename WHERE UniqueColID= unique identifier for the error causing record
Then I did:
INSERT INTO tablename ([uniqueIdentifier],[ column 2],[column 3]) SELECT #UniqueIdentifierofErrorCausingRecord, column2, [column3] FROM TableName WHERE [uniqueIdentifier]=#UniqueIdentifierForWorkingRecord;
What the first statement does is delete the non working record then the 2nd statement reinserts that record with identical column values of the working record but with the UniqueIdentifier of the Non working record. This way I can go through each table to find which table is causing the error and then I can pinpoint which column of that table is the issue.
The specific issue in my case was DateTime.TryParse() because a table column value was inserted in improper format.. The code performed field population in one of the methods without a try and catch using the DateTime.Parse method.... After some testing it seems even a try/catch is not able to pick this error up as it is a javascript error..
Don't use Response.Write().
Instead, create a LiteralControl and add it to the page.
Use ClientScriptManager to add scripts to the page. Here's an example from MSDN:
// Define the name and type of the client scripts on the page.
String csname1 = "PopupScript";
Type cstype = this.GetType();
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Check to see if the startup script is already registered.
if (!cs.IsStartupScriptRegistered(cstype, csname1))
{
String cstext1 = "alert('Hello World');";
cs.RegisterStartupScript(cstype, csname1, cstext1, true);
}

Categories