Saturday, November 26, 2011

WatiN Page Model, FindBy attribute on a property throws a System.ArgumentException


While running WatiN tests in NUnit, I faced this exception as soon as I initialized a page object
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
at WatiN.Core.Composite.InitializedProperty.SetValue(Object instance, Object value)
at WatiN.Core.Composite.InitializedMember.Initialize(Object instance, IElementContainer container)
at WatiN.Core.Composite.InitializeContents(IElementContainer container)
at WatiN.Core.Page.InitializeContents()
at WatiN.Core.Page.Initialize(Document document)
at WatiN.Core.Page.CreatePage[TPage](Document document)
at WatiN.Core.Document.Page[TPage]()
System.ArgumentException : Property set method not found.

This would occur as soon as I created an instance of a page class.
PurchaseSubPage pspage = browserinstance.Page<PurchaseSubPage>();
In the automation framework, that we had used, we had modeled each and every page in the UI as a class and extended our own set of controls that would perform actions that were specific to our application.

After delving into the PurchaseSubPage class, I came across this section, in which a FindBy attribute was not removed. 
[FindBy(IdRegex="_GridView_ProductsCoveredUnsupported$")]
            protected ITAMGrid unsupportedproductscoveredresultsgrid;
            [FindBy(IdRegex = "_GridView_ProductsCoveredUnsupported")]
            public override ITAMGrid ResultsGrid
            {
                get
                {
                    return unsupportedproductscoveredresultsgrid;
                }
            }
The FindBy attribute on the ResultsGrid property was the culprit and on removing it, harmony and order were restored. 

Wednesday, May 18, 2011

When Strings don't match in WATIN

The last week while I was working with a co-worker, I ran into this strange problem with WATIN on attempting a string based constraint search on a web page.
The item in question was a Business Objects InfoView report on which the filtering capability was to be tested.
The filter was a normal drop-down list


There was nothing unusual about this element and it was rendered as an usual select list and it appeared like one of those usual select lists that could be identified by specifying a Constraint for the Title.


However, that wasn't the case. Since this was enclosed within a frame, we needed to identify the Frame object first. After having done that we tried a
We tried setting a title based constraint using the following code
SelectList uniqValueFilter = DrillBar.SelectList(t => t.Title.Contains("Drill filter on Asset Number"));
But this just would not work. An interesting thing that we found was, if we did a COPY from the Developer Toolbar window and pasted it into Visual Studio, the same line of code would work and the SelectList object would exist.
However, if we keyed it in, it would not. The copy - paste approach wasn't an option for us because we wanted to test for different reports and the SelectList would be identified using input from a XML file.

However, this provided us with a valuable clue that there was an inconsistency in the character format. We tried a few approaches that did not work, and then we decided to  inspect it further

string title = "Drill filter on Asset Number";
char[] titlefromDEVTOOLBAR = title.ToCharArray();
title = "Drill filter on Asset Number";
char[] titlewhenkeyedin = title.ToCharArray();

A good look at the character arrays inside a quick watch window gave us more details about the issue.

The "space" character when pasted from the Browser was a char 160 instead of a char 32 that was keyed in.

A simple workaround could be to replace the character 160 before doing a comparison.
SelectList uniqValueFilter = uniqValueFilter = DrillBar.SelectList(t => t.Title.Replace((char)160, ' ') == "Drill filter on Asset Number");


But an approach like this would have been a work around and not a proper solution. The character 160 was a nbsp that occurs in HTML. So, we decided to constraint the selection of the SelectList based on the presence of all the individual words that formed the string.

SelectList uniqValueFilter = DrillBar.SelectList(BuildTextConstraintforSpaces("Drill filter on Asset Number"));
private Constraint BuildTextConstraintforSpaces(string filterstring)
{
string[] tempArray = filterstring.Split(' ');
Constraint textby = Find.Any;
foreach (string temp in tempArray)
{
textby = textby.And(Find.ByText(new Regex(temp, RegexOptions.IgnoreCase)));
}
return textby;
}
This has worked as expected without causing any pain.

Friday, February 18, 2011

Web Performance Tests - Context Parameters and Dynamically generated ASP.NET mangled IDs

The application that I was coding tests for, uses dynamically generated names for all the form post parameters.
For e.g. in case of the following line of code
request6Body.FormPostParameters.Add("_hdn_ctl00_ContentPageTabSectionPlaceHolder_WebPartManager1_wp680433384_wp384219079_CompanyAdditionalInfo_FormView_CompanyAdditionalInfo_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted"
 , this.Context["$HIDDEN1._hdn_ctl00_ContentPageTabSectionPlaceHolder_WebPartManager1_wp680433384_wp384219079_CompanyAdditionalInfo_FormView_CompanyAdditionalInfo_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted"].ToString());
the, _WebPartManager1_wp680433384_wp384219079_ will change to _WebPartManager1_wp101957077_wp105468996_ or to something unpredictable on different deployments.

This occurs for about 40~50 form post parameters. However, the rest of the part of the hidden parameters is constant.
I came across a lot of articles posted related to debugging a web test that were focused on how to extract hidden fields that are not getting extracted by the web performance test recorder. In my case, the hidden fields were getting extracted just fine, but a certain portion of the names are getting mangled (perhaps due to ASP.NET and dynamic field generation).

Finally after some effort, I came up with the following workaround

1.       Record the test using the Web Test Recorder and promote the dynamic parameters in it using Visual Studio.
clip_image002[5]
Identify the container controls on the page using the IE Developer toolbar. On the Company page there were three container controls for the page sections (formlets). And, the input controls were concatenated using $ instead of an _ as in the case of the hidden fields.
2.       In the preceding request, add an extraction rule (Extract regular expression) to identify the container controls and stored them in separate context variables.
3.       Perform a search and replace across all the requests
4.       At this point, the problem is that the form post parameters would be something like
                Name: _hdn_{{AdditionalInfoFormlet}}_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted
Value: {{$HIDDEN1._hdn_{{AdditionalInfoFormlet}}_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted}clip_image004[5]
                The context parameter value within another context parameter will cause problems during the test execution from a web test (performance web test).
5.       Now, generate a coded test from this performance web test.
The code generated will be like
request6Body.FormPostParameters.Add(("_hdn_"
                            + (this.Context["AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitte" +
                                "d")), (this.Context["$HIDDEN1._hdn_{{AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitte" +
                    "d}}"));
6.       Search and replace for the context parameters within the context parameters to correct them
request6Body.FormPostParameters.Add(("_hdn_"+ (this.Context["AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted")),
                                                (this.Context["$HIDDEN1._hdn_"+ this.Context["AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted"]).ToString());

7.       The regular expression extract rule was something like this in the generated code
ExtractRegularExpression extractionRule5 = new ExtractRegularExpression();
extractionRule5.RegularExpression = "ctl00_ContentPageTabSectionPlaceHolder_WebPartManager1_.*?_CompanyAdditionalInfo_" +
"FormView_CompanyAdditionalInfo";
extractionRule5.IgnoreCase = false;
extractionRule5.Required = true;
extractionRule5.Index = 0;
extractionRule5.HtmlDecode = true;
extractionRule5.ContextParameterName = "AdditionalInfoFormlet";
request5.ExtractValues += new EventHandler<ExtractionEventArgs>(extractionRule5.Extract);

ExtractRegularExpression extractionRule8 = new ExtractRegularExpression();
extractionRule8.RegularExpression = "ctl00\\$ContentPageTabSectionPlaceHolder\\$WebPartManager1\\$.*?\\$CompanyAdditionalI" +
"nfo\\$FormView_CompanyAdditionalInfo\\$";
extractionRule8.IgnoreCase = false;
extractionRule8.Required = true;
extractionRule8.Index = 0;
extractionRule8.HtmlDecode = true;
extractionRule8.ContextParameterName = "AdditionalInfoInput";

Thursday, June 04, 2009

Ubuntu and 4 GB RAM

I recently got a new PC and installed the 32 bit version of Ubuntu 8.04 LTS on it. However, I was dismayed to see that the RAM displayed as 3 GB even though I had installed 4 GB of RAM.

I recollected the same problem with Windows XP and it s inability to address more than 3 GB of RAM on a 32 bit Operating System.



Eventually, I stumbled on the fact that I had the following options

  1. Install the 64 bit version
  2. Recompile the Kernel with PAE support
  3. Upgrade to the server version of the Kernel which has PAE enabled

Options 1 and 2 sounded a bit of a waste of time and I decided to go with option 3.

This was pretty simple. All I had to do was to run the following commands in the terminal

sudo apt-get install linux-restricted-modules-server
sudo apt-get install linux-headers-server
sudo apt-get install linux-image-server linux-server

Voila, I had 4 GB of RAM available for use after that.



Thanks to samiux

Tuesday, March 31, 2009

Error on saving Fiddler session as Visual Studio Web Test

A couple of days back, I used Fiddler to save a session as a Web Test and curiously got this error..
--------------------------
Error during save...
---------------------------
One or more plugins returned an error, but the remaining plugins executed and the WebTest was written.
---
Could not load file or assembly 'Microsoft.VisualStudio.QualityTools.WebTestFramework, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

After going through this forum post, and modifying the Fiddler.exe.config file, I was able to save VSTS web tests using fiddler,

This was happening because, Fiddler was expecting Visual Studio 2005 assemblies and started complaining when it was not able to find them.

In order to work around this, we need to specify a binding redirect in the configuration file (fiddler.exe.config), so that the assembly resolver will resolve the 8.0 reference to the 9.0 assembly


<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="1" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.VisualStudio.QualityTools.WebTestFramework"
publicKeyToken="b03f5f7f11d50a3a"
culture="Neutral" />
<bindingRedirect oldVersion="8.0.0.0"
newVersion="9.0.0.0"/>
<codeBase version="" href="C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.WebTestFramework.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Tuesday, November 11, 2008

High resource consumption by ld-linux.so.2 on Ubuntu 7.10

At random intervals, the memory consumption of a particular process i.e. ld-linux.so.2 would rise abruptly high, and at times, the processor usage would rise too. The culprit in my case was Adobe Acrobat Reader 8.0 and the solution was simple too. There is a package lsb (Linux Standard Base) which will be used by Adobe Acrobat instead of ld-linux.so.2 if available.

I dont mind using Evince or other pdf viewers, but I need Adobe Acrobat Reader to view some portfolios generated using the Adobe Acrobat Office pluging containing multiple pdf s one file.

Running VMWare ESXi on Low End Hosts

In order to evaluate ESXi for use in test environments, I had installed it on a low end host (a DELL Optiplex GX520 desktop) and tried to run two virtual machines on it. However, when I would try to start the second virtual machine, it would throw an “Admission check failed for Memory Resource” error on me. I wasn’t able to figure out why this was happening as I had run two virtual machines with the same configuration on a host with similar resources using VMWare Server.

All that needs to be done is to modify the memory reservation in the resource allocation tab

1. Open the VMWare Infrastructure interface to the ESXi server
2. Select Configuration >> System Resource Allocation >>Advanced
3. Click on Edit Settings and edit the memory reservation and change it to 256 MB or lower (as per requirement)

Thursday, September 04, 2008

Identification of SQL Server Edition and Version

This query can be used to identify the SQL Server Version and Edition currently in use on a server.

SQL 2005
SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'), SERVERPROPERTY ('edition')

SQL 2000
SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'), SERVERPROPERTY ('edition')

SQL 7.0 and earlier
SELECT @@VERSION

The following is a KB article for this.
KB 321185: How to identify your SQL Server version and edition

Detecting the installed version of .NET

Open a command prompt and run the command

dir %systemroot%\microsoft.net\framework\v?.* /ad /b


This will list all the versions of .NET framework installed on the system