One of the benefits of asp.net mvc is testing. Also multiple templates are available for views. I wonder, why not create some view engine for testing. It will allow to write tests declaratively (like vriting your markup, but adding assumptions and constraints). What do you think, is there any sense for that?
Made some investigations and see that currently poeple are using fake view engines to test their controllers. Here and here are 2 examples of this approach.
So in this context I`d say that idea of using views for testing purposes can be said like "Creating a view engine that will ease some default testing procedures".
By easing some testing procedures I assume the following:
Allow default checks, like checking for null, for equality or non equality to some types/objects.
Allow easy access to all things can be used to generate and fill a view. Its model, view data and so on. So that you can just write things like check model contain Customer and his name is John Smith or Products DropDownList has 5 products and allow to write this with some easy syntax. Like Model.Contains(Customer).CustomerName.Is("JohnSmith"), Model.Products.Contains(5). This is the one just came to my mind, I think there are better ways to write down test cases, that`s for sure, but I hope it gives the idea.
Allow to use Views that you already have to generate some tests using them. Would be great to have a kind of WebForms designer that allows you to generate parts of tests using parts of the view. I think this can boost the speed of test writing as you have enough context of what is going on and what need to be tested when see your View.
You might want to have a look at Fitnesse - see http://fitnesse.org. It is an acceptance testing framework that lets you put together acceptance tests in wiki form. This allows tests to be written, understood and executed by business users as well as by developers.
Related
I have to set up a Asp.net demo using MVC 4 in a web application in order to help decision for a product that currently don't use this pattern. The model, view and controller should be simple, I just have two or three entities and a few pages.
I suppose I don't have to implement the whole infrastructure with services, repositories, etc. So how could I simplify the MVC components without loosing those advantages?
The MVC components aren't related to the data access strategy which you can use. To put together a quick demo (or a simple application) you can leave the data access in the same project but eventually split that out etc.
You can use something like AutoMapper to map from your entities to your view models if you want to put that level of abstraction in. You can also use EntityFramework contexts in the controllers to avoid additional levels of abstraction and only put in a simple interface/abstraction into one controller to show unit test ability.
Small examples of different patterns which could be used in the application is probably the way to go for the demo/presentation and not worry too much about putting them in all over the place. Remember the presentation and the delivery of information is as important, it not more, than the demo code itself.
I learned basics of web-based integration testing using SpecFlow and WatiN. From what I understand, SpecFlow decides whether test has passed based on whether a specific HTML markup is present on the page - buttons, links, etc.
But doesn't that mean that my integration tests are tightly coupled to my UI? For example, if in feature ABC Watin looks for a specific HTML element to be present (let's say it's a table), and I suddenly change my UI so that this table becomes a bunch of divs, WatiN won't be able to find it and my test for feature ABC will fail. How can I avoid such situations?
My suggestions are -
a) I should write WatiN tests so that they are minimally affected by changes to UI design
b) I should make UI design so that WatiN still understands it if I change it
c) I should use some library with WatiN that is able to recognize UI design changes
Any suggestions? Where am I wrong?
EDIT
I'm an idiot - I forgot to mention I'm using ASP.NET MVC
First you should decide if you really need to go through the UI. Probably and especially if you want to convince a stakeholder that these specs actually are exercising the system. But later on you might want to hit the system on the domain layer or right under the UI (the controller in a MVC architecture for example).
You might even want to be able to switch between the two versions
Either way you want to abstract away from having a tight coupling between your step definitions and the actual application (be it the page or the controller).
One way to accomplish this is to use the Page object pattern which basically is an wrapper class for the page you're testing. This class gives you a nice interface to interact with the page (for example a method for submitting a form, properties for fill out the form and other properties to query the page for content).
How you actually interact with, or automate, the page is "hidden" within the page object and only need to change this one place if (when?:)) it changes.
This is not perfect of course, you still have a "tight" coupling to the page, but is now abstracted away in a separate class and that is at least a little better.
A tip is to try to keep you step definitions short. Super short - a single statement or row. And the move the rest of the logic down into an automation layer.
Also don't miss this great presentation by Matt Wynne that shows this in great effect.
We're building about 10 ASP.NET MVC sites which have a common set of features (and corresponding URLs, Routes, Controllers, Actions, and Views). The sites will also all share a base set of domain objects (e.g. users, companies) and base attributes on those objects (e.g. name, address, etc.).
But each site will also be highly customized and extended from the base. For example, our site for large, public companies will have "Subsidiary" and "Stock Symbol" fields on the Company domain object, while our site for startups will have a "Venture Firm" and and "Funding" attributes. Look and feel will also vary considerably, although we're trying to keep HTML as consistent as possible (modulo extra form fields for extra domain object attributes, etc.). We'll also be overriding images sparingly, so we can, for example, re-use the same button graphics across sites.
Anyway, we're trying to figure out how best to factor and architect things so that we can reuse as much code and as many tests as possible without limiting our freedom to add per-app attributes and vary the UI between apps.
I'm familiar with how to handle limited-customization multi-tenancy like you find in StackOverflow/SuperUser/ServerFault (or MSDN/TechNet for that matter), where the UI is a little different and the data model is more-or-less identical. But when the models and UI are very different (but inherit from a common base), I'm less sure how to proceed.
I'm less worried about operational issues, since we'll probably be running each site in a separate appdomain and hosting them on separate databases. I'm more worried about reducing long-term code maintenance costs, increasing agility (e.g. easy to add new features to the base without breaking derived apps), and realizing short-term dev-/test-cost savings as we build our 2nd, 3rd, 4th, etc. site.
I'm looking both for high-level guidance and suggestions, but also concrete suggestions for how to make that guidance real using modern ASP.NET MVC practices.
I realize this is a very general question, but for starters I'm looking for both high-level guidance as well as concrete tips-n-tricks for how to apply that guidance with ASP.NET MVC, including things like:
recommendations where to split base/derived across Visual Studio projects
source control tips to avoid forking
database schema tips (FWIW, our databases are all small-- under 10K rows per table, so dev/test cost is more of an issue than DB perf)
tips about re-using Controllers/Views/etc. corresponding to the "base" model attributes, especially re-using UI for things like "new customer" forms which will have a mix of base and derived attributes.
Anyone have good advice for how to architect a multi-tenant app like this?
Here's what we do, and it works pretty well for about 8 sites currently.
Define a core MVC project for your Controllers, ViewModels, HttpApplication, routes, etc. This will compile into a DLL and compromise the bulk of your site.
Create a basic set of default views, scripts, images, etc. for your site. These will server as defaults for your individual sites.
Per client, create any custom controllers, routes, etc that you'll need in a project that compiles to another dll.
Also per client, recreate any views, scripts, images that you'll want to use.
To make the above steps work together you'll need to write a little glue. The first piece of glue is a custom view engine. You'll want to customize the standard view engine to first look for views in your client-specific folder, and then the default folder. This lets you easily override the default layout per client.
The second method of getting everything working is to have your core application load the routes, controllers, etc from your client specific assembly. To do this I use the Managed Extensibility Framework (MEF) to expose a single Register method. Calling this method on my client assembly code registers the routes and any other client-specific needs.
Here's a general view of what my site folder structure looks like, with SiteContent being checked for views first:
- AppContent
- AppContent/Static
- AppContent/Static/Images
- AppContent/Static/Scripts
- AppContent/Static/Styles
- AppContent/Views
- AppContent/Views/Shared
- SiteContent
- SiteContent/Static
- SiteContent/Static/Images
- SiteContent/Static/Scripts
- SiteContent/Static/Styles
- SiteContent/Views
- SiteContent/Views/Shared
- web.config
- Global.asax
I have helpers that I can use like SiteImage and AppImage for use in my views. Also, I make each of my client sites use certain specific names for their master pages, that I don't ever define in my AppContent defaults.
I realize this is a rough overview, but it is working well enough for us right now.
I'm involved in a similar type of "suite" of projects currently which is focused on allowing customers to apply for products online but have very similar requirements for what information to collect, where the only differences are around product specific pieces of information or slightly different legislative requirements.
One thing that we have tried to do is create pages (model, view and controller combinations) that are reusable in themselves, so any application can use the page to capture information but redirect to the next page which may be different depending on what type of product is being applied for. To achieve this we are using abstract base controllers in the form of the template method pattern that contain basically all the required controller logic (including action methods with their applied action filters) but then use abstract methods to do the specific stuff such as redirecting to the next page in the process. This means that the concrete implementation of the controller used by specific application page flows may contain only one method which returns a RedirectToActionResult corresponding to the next page in the flow.
There is also quite a bit of other stuff that handles going backwards and those kinds of navigational things, but with the help of action filters you can get it set up that you don't have to worry about it once you get it up and working.
There are also base model objects which contains common functionality, be it validation logic or state persistence logic.
The data captured during the application process is persisted in database as xml serialized model objects which can then be pulled out and de-serialised once the application is completed and spat out in whatever format to whatever system the backend operations staff use to process applications.
The implications of this is that we have a project structure that consists of a base dll that contains top level abstract classes, interfaces and utility classes as well as html helpers, action filters etc. Then we have mvc projects which contain the concrete implementations of the base controllers, models etc as well as the views and masterpages.
The hardest thing is sharing views and I don't think we have properly got this sorted yet. Although with MVC 2.0 containing Areas I think this will become less of an issue but I haven't had a good play with it yet. (see Scott Gu's post on 2.0: http://weblogs.asp.net/scottgu/archive/2009/07/31/asp-net-mvc-v2-preview-1-released.aspx)
One thing I have POCed that looks like it will work is using a base MVC project to contain common views and then extending the default view engine to search that project on the web server when looking for a view to render (which is quite easy to do). Areas though is a far nicer solution.
As for source control, we are using svn and I think you are reasonable in being concerned about branches. It is not something that we have had to deal with yet, but we are probably going to go with git as it seems to make the process of branching and merging much less painful.
Not sure whether this helps you much but I would definitely recommend keep in mind abstract controllers and models, and also look at how you can use html helpers and and partial views to group similar pieces of functionality.
Mike Hadlow goes into good detail on how to accomplish this:
http://mikehadlow.blogspot.com/2008/11/multi-tenancy-part-1-strategy.html
One way to do this is to use branching in a source control system.
The main branch is for the common functionality. You then have a branch for customization and can merge changes out to the customization or back to the main branch.
What is the best and cleanest way to implement A-B testing in asp.net mvc? That is, when we make new changes to an asp.net mvc web site, we want to test the new html/css/js with a certain subset of visitors (defined on cookie, login id, etc) and then analyze some metrics (page response time, number of pages visited, $$$ in sales, etc) afterwards to measure the level of success of the changes.
I am looking for a clean way to implement a way of choosing what view (html/css/js, etc...) to render using asp.net mvc.
Check out FairlyCertain (http://www.fairtutor.com/fairlycertain/) when you get a chance. It's a .NET A/B library that you can pretty much just drop into your project and start writing tests.
Unlike the Javascript libraries from Google and VisualWebsiteOptimizer, everything happens on the server so you don't suffer any performance, user experience or SEO issues. I've been using it in my stuff for a while now and it works quite well.
There is an A/B testing framework specifically for ASP.NET MVC. This is an open source software I wrote myself when, just like you, didn't find a free tool which works nicely with ASP.NET MVC and doesn't require much setup.
Google Content Experiments? It's a Javascript-based solution that doesn't require anything from your backend.
You include Google's Javascript on your page
The script randomly substitutes elements on your page as defined by your A/B test
Google's site shows you a nice breakdown of the results...
If you are using the spark view engine, you could probably do it with a variation of the theme filter (http://sparkviewengine.com/documentation/viewlocations#Extendingfilepatternswithdescriptorfilters). For each new visitor to the site, determine if you want them to see the existing or new version of the site and set a cookie. Wire up a descriptor filter that looks for the presence of the cookie and modify the view location to look in the folder containing the modified views. If an alternative view exists, the Spark engine will automatically render it in place of the "normal" view, otherwise it will render the normal view.
If you are using the normal WFVE, then the simplest way to manage this would be to define a folder under Views where your view alternatives live. When you want to provide an alternative view, you place it in a location that matches its position within the normal Views folder but rooted at the alternatives folder e.g. to provide an alternative to Views/Users/login.aspx place your new view at Views/Alternative/Users/login.aspx.
With a convention in place for locating your alternative views, you can extend the WebFormViewEngine and overload CreatePartialView / CreateView to inspect some aspect of the ControllerContext to determine whether to render the default or overloaded view and alter the path as appropriate e.g. changing .../Views/Users/login.aspx to .../Views/Alternative/Users/login.aspx.
I suggest you use Display Modes to achieve A/B testing.
But Display Modes just support simple problems by default.
If you already implement Display Modes in some other scenario. You can consider DisplayModeMatrix (just google it). It helps you use Display Modes more efficiency.
https://www.nuget.org/packages/DisplayModeMatrix/
Wth Display Modes you can simply delete/rename views after A/B testing to clean up your project.
I think there isn't a ready to use solution for this and you will have to improvise.
Try to override your current functionality in well defined points without breaking it. Explicitly draw a border where your regular code and A-B testing code lives.
Inversion of control principle might help a lot here too (i.e. - controller factory could provide derived controller instead of original one). For views&partialviews - you could change viewengine so it would try to look for 'MyPartialViewAB.ascx' instead of 'MyPartialView.ascx'.
And it might be a good idea to take a look what performance counters are (in case you haven't).
Most of the stackoverflow posts about ASP.NET MVC unit testing talk about a specific issue or specific thing to test such as testing HtmlHelpers. Others on the subject of best practices have surprisingly few answers. Available videos I have watched are completely useless in my opinion - and mind blowingly long (by the time you've watched 1.5 hours and not learned anything).
What I want to know from people who've actually been doing this is :
What are the most important things to test first
What doesn't need testing (shock horror for me saying that but I'm not after 100%)
What is hard to test and how have you overcome difficult thins to test.
What things can break in refactoring that a test won't catch.
I'm not new to how to unit test - but I'm very new to actually doing it consistently. I'd really appreciate lessons learned from those who are experts in unit testing ASP.NET MVC.
I'm really looking for specific things you might only find out after having tried it - not jsut general advice like 'use interfaces' - although of course any suggestions are welcome.
Oh and lets say I've decided to use Microsoft's unit testing - just becasue its already there. I think all answers would apply to all testing frameworks though.
Test your routing. You should use RouteLink to remove ambiguity when you generate a URL in your View, but when you submit a URL, you are dependent upon the routing system to select the correct route. So test that the URL patterns you support do in fact return the correct route.
Test your controller actions. Use a mock repository, and test that manually invoking each action has the results you expect.
Test all business logic in your model. This is obvious, and little different from non-MVC applications.
Test any custom view helpers you write. Although I don't generally unit test views, view helpers are different.
Test your JavaScript. There are unit testing frameworks for this, that testing JavaScript is so easy that such frameworks are hardly necessary. But testing JavaScript is incredibly important, due to the tendency of the language to hide errors from you.
If you have written any custom model binders, they need special attention. For one thing, it is a lot easier to debug a model binder via a unit test than when it is "live" in the application.
I'd like to elaborate on testing controller actions:
Verify you get the proper ActionResult. A redirect is different from a view.
Also verify the expected view name. If you rely on the default view, it should be empty.
Verify you get the proper view model.
Verify all branches in your action. Keep them to a minimum and move them to a helper / service when they grow too many.
In short, verify anything from the ActionResult that you will use.
I dont think the answer has to be specific to ASP.NET MVC.
Like any other application, the most important thing you have to test is your core logic.
That is, your model code and your controller actions.