Does anyone do automated QA testing for a Classic ASP site? I started looking at WatIn and MBUnit but not sure of the best way to structer the tests.
The new WatiN 2.0 beta 1 does offer some base classes to help you structure test classes.
It basically comes down to having a class for each page (inheriting the WatiN.Core.Page class). In these page classes you add properties for each control you want to access. Something like:
public Button OkButton
{
get { return Document.Button("okbuttonId");
}
and you can create methods to wrap some more complicated actions an a page. For instance:
public void AddPerson(string name, string email)
{
/// logic goes here tp click on NewButton, set the textfields and click on OkButton
}
These page classes offer the advantage of defining your elements in one place.
In your test code you can create a page class as follows:
using(var ie = new IE("www.somedomain.com/person"))
{
var page = ie.Page<PersonDetailPage>();
page.AddPerson("J. Doe", "jdoe#example.com");
// Do some Assert
}
Another interesting base class to help you structure your code is the Control class. When you use ASP you'll use controls which will not render to just one html element in the rendered page. Instead it will often be a construct of elements contained in a Div element. When creating your own control class and inherit Control you'll be able to wrap the controls (html) internals and behavior. This makes it very easy to reuse the control in your page classes. Following an example on how to instantiate a control:
var calendar = Document.Control<CalendarControl>("calendarId");
Hope this gives you some insight in how you can structure your Pages and controls.
Jeroen
FWIW, we have been using WatiN and MbUnit for web integration testing for the past 3 years.
We have separated the tests into 3 projects:
QA.Framework: Contains glue code for setting up test fixtures and various custom MbUnit and WatiN extension.
QA.SiteMap: Contains Page and Control classes arranged hierarchically into namespaces that correspond to different domains and parts of the sites. This project serves to decouple tests from the major part of the web site structure. You can think of it as a model of the sites.
QA.Tests: Contains the actual tests also arranged hierarchically into namespaces. Tests leverage the SiteMap and Framework as needed to interact with the web site. This way there is much less code duplication than if each test contained the same button ids over and over...
Jeff.
I tested ASP site with Watir. If you are looking for a way to structure tests, take a look at WatirCraft framework.
Related
I am currently working on multiple ASP.NET MVC web apps.
All of these web apps have the same navigation bars/menus.
Some of the menu items are app specific, so they can be passed from the respective app.
Some of the menu items are not app-specific, such as whether user is admin or not, based on which I show an admin link on the nav bar. The logic for getting the admin property is available in the business layer.
Is it possible to make this html helper such that I don't have to pass the non-app specific parameters from the respective apps ?
Can I call the business layer from the html helper ?
Is it advisable ?
I want this html helper or any other solution easily distributable...
Thanks
HTML helpers are extension methods on the System.Web.Mvc.HtmlHelper type that return an System.Web.Mvc.MvcHtmlString object. If you want "easily distributable", then you can create a library project with the helper extensions that you need. Then add the project in as a reference on the MVC project.
#using statements can bring in the extensions to the Razor view. The helper object that you bring in through the extension method in the library will give you access to most of the information available to the Razor view at the time the helper is called (with the ViewContext property).
The extensions can be overloaded as much as needed to account for variations in the projects. Common menu options can be added to the library as a static collection that can be accessed by both the MVC project and the extension methods.
update
MVC is set up such that you can do what you want. You have a lot of control. Your helper can include as much code as you need. It's not like you are "breaking the rules". But best practice dictates that you keep your business logic in the controller. By putting that into the helper, which gets called by the Razor view, you are in effect moving the business logic into the Razor view.
HTML Helpers in general are a lightweight way to create HTML code. Thus they are easy to reuse any you can have dozens or hundreds on a single Razor view. That idea gets broken when you move a bunch of business logic into the helper. Then you have a potential of slowing things down if the helper is to be reused a lot.
Good rule of thumb for MVC, if your helper starts getting complicated, create a partial view. I would probably create a model to represent the menu, then create a partial view in the Shared folder that uses that model, then call it from the parent view. I think that would give you more flexibility, and be more in keeping with the MVC best practices.
Is there a way to reuse a piece of ASP.NET code (that tag-based code, not the code-behind) in many different pages? For example I have a <div> with some contents in it that appears in 5 different pages of my site. I'm looking for a technique through which I could save this <div> in a separate web-content file so to speak, with maybe a different extension like MyDiv.ASPC and could then do a server-side tag anywhere in a webpage like:
<asp:Import href="~/MyDiv.aspc" />
and ASP.NET would inject the entire content of this file at that point where this tag appears.
I thought of creating a user control for this, but I'm not sure if a user control always injects precisely what is written in its body, or could there sometimes be unwanted tags generated by user control itself.
Or are there existing better ways of doing this?
Edit
About Master Pages, they are far away from what I'm looking for. They are actually good for a common basic layout of your website. My idea is quite opposite of that. My pages do not have a common layout; it is just that they have one common <div>. It is more closely fulfilled by a UserControl.
For UCs, my fear is that they generate more than what is written in their body, whereas what I'm after is a simple text injection. To put it technically, what I'm looking for is basically a preprocessor step (kind of #include thing in C++) rather than a compiler step, if you see what I mean.
You need to use ASP.NET User Controls, as these are specifically created to be the solution to the problem you are describing. For more information, see MS Documentation.
From their documentation...
In addition to using Web server controls in your ASP.NET Web pages,
you can create your own custom, reusable controls using the same
techniques you use for creating ASP.NET Web pages. These controls are
called user controls.
A user control is a kind of composite control that works much like an
ASP.NET Web page—you can add existing Web server controls and markup
to a user control, and define properties and methods for the control.
You can then embed them in ASP.NET Web pages, where they act as a
unit.
An empty userControl would do just that - nothing. A user Control just adds it's contents to the page, or usercontrol hosting it. It adds nothing extra.
UserControls give you a nice easy page fragment type approach to reusing content. They work great within a project & most people use them for just that.
If you wanted to make something more reusable across projects, you could write server control. It's more involved, but much more reusable. Google should be able to find you many tutorials on how to do this.
Ran a short test. User Controls do not enter extra tags as long as you don't place any Runat="Server" tags in it, so this would indeed be a solution I guess.
You can also read output from a cache object where you would read your files.
So
<%= Static.ContentXyz %>
would mean:
public static class Static
{
public static string ContentXyz
{
get
{
string s;
if (!this.cacheDictionary.TryGetValue("ContentXyz", out s))
{
s = File.ReadAllText(Server.MapPath("ContentXyz.html"));
this.cacheDictionary("ContentXyz", s);
}
return s;
}
}
}
As a web developer I feel too much of my time is spent on CSS. I am trying to come up with a solution where I can write re-usable CSS i.e. classes and reference these classes in the HTML without additional code in ASPX or ASCX files etc. or code-behind files. I want an intermediary which links up HTML elements with CSS classes.
What I want to achieve:
Modify HTML immediately before transmission
Select elements in the HTML
Based on rules defined elsewhere (e.g. in a text file relating to
the page currently being processed):
Add a CSS class reference to multiple HTML elements
Add multiple CSS class references to a single HTML element
How I envisage this working:
Extend ASP.NET functions which generate final HTML
Grab all the HTML as a string
Pass the string into a contructor for an object with querying (e.g. XPATH) methods
Go through list of global rules e.g. for child ul of first div then class = "navigation"
Go through list of page specific rules e.g. for child ul of first div then class &= " home"
Get processed HTML from object e.g. obj.ToString
ASP.NET to resume page generation using processed HTML
So what I need to know is:
Where / how can I extend ASP.NET page generation functions (to get all HTML of page)
What classes have element / node querying methods and access to attributes
Thanks for your help in advance.
P.S. I am developing ASP.NET web forms websites with VB.net code-behinds running on ISS 7
Check out my CsQuery project: https://github.com/jamietre/csquery or on nuget as "CsQuery".
This is a C# (.NET 4) port of jQuery. In basic performance tests (included in the project test suite) selectors are about 100 times faster than HTML Agility Pack + Fizzler (a css selector add-on for HAP); it's plenty fast for manipulating the output stream in real time on a typical web site. If you are amazon.com or something, of course, YMMV.
My initial purpose in developing this was to manipulate HTML from a content management system. Once I had it up and running, I found that using CSS selectors and the jQuery API is a whole lot more fun than using web controls and started using it as a primary HTML manipulation tool for server-rendered pages, and built it out to cover pretty much all of CSS, jQuery and the browser DOM. I haven't touched a web control since.
To intercept HTML in webforms with CsQuery you do this in the page codebehind:
using CsQuery;
using CsQuery.Web;
protected override void Render(HtmlTextWriter writer)
{
var csqContext = WebForms.CreateFromRender(Page, base.Render, writer);
// CQ object is like a jQuery object. The "Dom" property of the context
// returned above represents the output of this page.
CQ doc = csqContext.Dom;
doc["li > a"].AddClass("foo");
// write it
csqContext.Render();
}
To do the same thing in ASP.NET MVC please see this blog post describing that.
There is basic documentation for CsQuery on GitHub. Apart from getting HTML in and out, it works pretty much like jQuery. The WebForms object above is just to help you handle interacting with the HtmlTextWriter object and the Render method. The general-purpose usage is very simple:
var doc = CQ.Create(htmlString);
// or (useful for scraping and testing)
var doc = CQ.CreateFromUrl(url);
// do stuff with doc, a CQ object that acts like a jQuery object
doc["table tr:first"].Append("<td>A new cell</td>");
Additonally, pretty much the entire browser DOM is available using the same methods you use
in a browser. The indexer [0] returns the first element in the selection set like jquery; if you are used to write javascript to manipulate HTML it should be very familiar.
// "Select" method is the same as the property indexer [] we used above.
// I go back and forth between them to emphasise their interchangeability.
var element = dom.Select("div > input[type=checkbox]:first-child")[0];
a.Checked=true;
Of course in C# you have a wealth of other general-purpose tools like LINQ at your disposal. Alternatively:
var element = dom["div > input[type=checkbox]:first-child"].Single();
a.Checked=true;
When you're done manipulating the document, you'll probably want to get the HTML out:
string html = doc.Render();
That's all there is to it. There are a vast number of methods on the CQ object, covering all the jQuery DOM manipulation techniques. There are also utility methods for handling JSON, and it has extensive support for dynamic and anonymous types to make passing data structures (e.g. a set of CSS classes) as easy as possible -- much like jQuery.
Some More Advanced Stuff
I don't recommend doing this unless you are familiar with lower-level tinkering with asp.net's http workflow. There's nothing at all undoable but there will be a learning curve if you've never heard of an HttpHandler.
If you want to skip the WebForms engine altogether, you can create an IHttpHandler that automatically parses HTML files. This would definitely perform better than overlaying on a the ASPX engine -- who knows, maybe even faster than doing a similar amount of server-side processing with web controls. You can then then register your handler using web.config for specific extensions (like htm and html).
Yet another way to automatically intercept is with routing. You can use the MVC routing library in a webforms app with no trouble, here's one description of how to do this. Then you can create a route that matches whatever pattern you want (again, perhaps *.html) and pass handling off to a custom IHttpHandler or class. In this case, you're doing everything: you will need to look at the path, load the file from the file system, parse it with CsQuery, and stream the response.
Using either mechanism, you'll need a way to tell your project what code to run for each page, of course. That is, just because you've created a nifty HTML parser, how do you then tell it to run the correct "code behind" for that page?
MVC does this by just locating a controller with the name of "PageNameController.cs" and calling a method that matches the name of the parameter. You could do whatever you want; e.g. you could add an element:
<script type="controller" src="MyPageController"></script>
Your generic handler code could look for such an element, and then use reflection to locate the correct named class & method to call. This is pretty involved, and beyond the scope of this answer; but if you're looking to build a whole new framework or something this is how you would go about it.
Intercepting the content of the page prior to it being sent is rather simple. I did this a while back on a project that compressed content on the fly: http://optimizerprime.codeplex.com/ (It's ugly, but it did its job and you might be able to salvage some of the code). Anyway, what you want to do is the following:
1) Create a Stream object that saves the content of the page until Flush is called. For instance I used this in my compression project: http://optimizerprime.codeplex.com/SourceControl/changeset/view/83171#1795869 Like I said before, it's not pretty. But my point being you'll need to create your own Stream class that will do what you want (in this case give you the string output of the page, parse/modify the string, and then output it to the user).
2) Assign the page's filter object to it. (Page.Response.Filter) Note that you need to do it rather early on so you can catch all of the content. I did this with a HTTP Module that ran on the PreRequestHandlerExecute event. But if you did something like this:
protected override void OnPreInit(EventArgs e)
{
this.Response.Filter = new MyStream();
base.OnPreInit(e);
}
That would also most likely work.
3) You should be able to use something like Html Agility Pack to parse the HTML and modify it from there.
That to me seems like the easiest approach.
I have just started to learn ASP.NET MVC. When comparing ASP.NET MVC with Web Forms one of the main advantage of MVC is always told to be better support of Unit Testing. Can I got a good explanation of how it has better support?
Edit :
If possible please provide example in both.
Asp.Net MVC has better unit testing support for one main reason - the whole architecture is built to use HttpContextBase, HttpRequestBase and HttpResponseBase.
Asp.Net webforms is dependent on HttpContext.Current, which is a singleton that you have no control over - it is set up and passed to your pages as part of the HttpApplication executing the request. In most cases, in order to get the page to execute correctly, you need to execute it in a real HttpContext. Since many of the properties of HttpContext are not settable (like Request and Response), it is extremely difficult to construct fake requests to send to your page objects.
This makes unit testing webforms pages a nightmare, since it couples all your tests to needing all kinds of context setup.
Contrast that to ASP.Net MVC, where you can mock an HttpContext! Now your code doesn't even need a web server to give it context, you can just set up the bits you need, and hand the mocked context to your method.
The ASP.NET page lifecycle makes it incredibly difficult to unit test classes that derive from Page, which starts out with too many responsibilities and becomes a god object when you add application logic to it. Even worse, it has hidden dependencies on static classes and requires a default parameterless constructor, which limits your ability to inject dependencies.
So, to make an ASP.NET WebForms page testable, you need to take all the logic out of your code-behinds and put it in another class - typically a Presenter as in the Model-View-Presenter pattern.
ASP.NET MVC controllers are already separated from their templates and aren't encumbered by the ASP.NET page lifecycle.
Because you can create a controller object in your unit test, call some actions on it, and see the result right away, then you can Assert.IsBlahBlahBlah(); on it.
For example,
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
With that method, you now know that your Index view is returned from the Home controller.
If you want to use ASP.Net WebForms (like i do) and unit tests together, take a look at this:
WebForms MVP on codeplex
Works for me.
It's far more cumbersome to test a code behind page than to test a controller. With the MVC pattern, there's a more logical separation of presentation logic thus making it easier to write tests.
You can do exactly the same thing with Web Forms, it's just that people who don't know better write code that can't be tested this way.
There's no reason to have business logic in a codebehind class. Same with data access logic. Even right there, that lets you test the parts of the application most subject to both bugs and testing.
Some might say that doesn't allow you to test for button clicks and other user-interface events. If you want to do that, then you can go ahead and create your own MVC or MVP or other such pattern, that does use a separate interface for the user interface actions. Then do exactly the same kind of test you'd do if using ASP.NET MVC.
And you still have the problem of not being able to test client-side code.
Slightly OT but you may want to look at Selenium for Unit Testing webpages....
In reference to Lawrences suggestion about Selenium, there is also WatiN.
This is not specific to MVC, but I think MVC definitely helps in that it keeps element ids and classes clean and easier to target from the test.
With WatiN you can do the following (example from their site).
[Test]
public void SearchForWatiNOnGoogle()
{
using (var browser = new IE("http://www.google.com"))
{
browser.TextField(Find.ByName("q")).TypeText("WatiN");
browser.Button(Find.ByName("btnG")).Click();
Assert.IsTrue(browser.ContainsText("WatiN"));
}
}
In traditional ASP.NET Web Form applications, UserControls are a great way to encapsulate functionality so that it can be reused. However, UserControls don't fit well into the MVC model. They often make heavy use of ViewState and they blur the seperation of concerns that MVC promotes.
My question is, how do you best bundle a piece of functionality so it can be shared across MVC applications?
As an example, consider a from/to date-selector UserControl that:
allows a user to select two dates, either using a javascript overlay or by typing in day, month and year into seperate fields
can be configured to default to either today and tomorrow's dates or to dates of the developer's choosing
validates the dates that comes back from the user to ensure the from date is before the to date
exposes From and To properties that can be accessed by code-behind
How would I best build something like this in .NET MVC so that I can easily reuse it?
Note that to fully emulate User Control's functionality the MVC component would have to manage the submitted form data and validation - not just the presentation.
In general I would agree that user controls are nice in terms of encapsulating UI stuff, but I don't think too much has really changed in MVC. If I remember right re-using user controls across classic Asp.net projects was a pain and was never really the best way to truly create reusable components. Most UI toolkits that you bought for classic ASP.net didn't give you user controls, they gave you essentially server controls and javascript controls.
In your example, I would probably create or find a jquery (or ur framework of choice) plugin that did what you wanted on the client side. You could also build a C# wrapper around it similar to what Telerik did with some of the jquery UI controls. I do think that the word code-behind and even viewstate will disappear from your vocabulary the more you get into MVC.
If you look at what open source projects are out there for MVC you will get your answer in terms of what you should be doing.
The MVC Contrib app adds a lot of features by creating extension methods and helpers. Their grid control is a typical way to create a reusable component that you could use across projects
Telerik, created some extensions that wrap jquery controls and do asset management.
Finally I think if you look to the future, MVC has areas, which if I interpret it right will give you the ability to break your project apart into multiple smaller projects.
Besides what is already suggested, ASP.NET MVC v2 will have generic templated input controls, see here. You can read how other people do similar techniques, for example, here:
We have
exactly 1 method call for generating a
form element, “Html.InputFor”. As
part of that “InputFor”, it examines
an input specification, that collects
the PropertyInfo, any attributes, the
type, any modifiers called, and
selects an appropriate InputBuilder.
Call InputFor(p => p.Id) and Id is a
GUID? That creates a hidden input
element. Call InputFor(p =>
p.Customer.Address) and Address is a
complex type? That looks for a
partial with the same name of the type
Having considered the helpful answers from others, I will have a go at answering my own question.
It seems to me that the key difficulty with emulating UserControls in MVC is that they crosscut the concerns that MVC aims to seperate. The from/to date selector UserControl in my example incorporates elements of Model, View, Control and interation. UserControls' ability to bundle all this together is exactly the reason that they don't fit well into MVC.
That means that to create a psuedo-UserControl in MVC requires four seperate pieces:
A Model class - in this case an Interval class or similar
A PartialView that knows how to render the Model to HTML
A jQuery script to layer interactivity on top of the PartialView's HTML
A ModelBinder that can deserialise postdata into an instance of the Model class.
The ModelBinder is important because it deals with data coming back from the user. Without it, every Controller that wanted to display a to/from date selector in any of its Views would have to know how to assemble the six postdata fields - and how to cope if they were invalid or some were missing.
Two ways that I can think of. A partial view though this doesn't really transfer well from app to app because you are moving around ascx files. Not a big pain but not my flavour.
I prefer to use WebControls. They are super easy in mvc and all you need to do is reference the library in the project and possibly in your config file and there you go.
I think some of the answers have missed out on the postback functionality of controls. One way you could handle that is to pass any generic information via ViewData when rendering your partial view. That could then post back to its own control, which in turn could redirect to the UrlReferrer.
Its a little messy and use of UrlReferrer poses a security risk. But it is one way around the problem
You can create a jQuery plugin.
As user-controls provided in ASP.NET Webforms, MVC provide a lot of ways to make the controls and code that can be reused in other app.
Using Partials If your partial code have some C# logic and render the html using Razor/aspx code then it's bst to maintain them in razor file.
Write JavaScript Functionality as plugin If you maintain your code and write it as better as it can be used in other app then it would be a huge advantage for you. Next time when you work on other app just open this solution copy it and modify it. Write JavaScript code that can be used as plugin maybe take some more brainstorming.
Write Code As a Separate C# library If some code is too common for every app you make.for example you write a member authentication system or some global function (C#) that are used in every app you made then maintain them in a separate solution so it can be used in other app you made whenever you trying to make a new app in future.