If all the business logic is present in a datamodule (TSQLDataSets and TDataSetProviders) how would you refactor the code to make the application more appropiate for unit testing?
After the last question about this, I wrote a blog post about how to do it.
Some basic tips:
Your DataModules should never have any references to forms or any other UI components
Put the TDataSources on forms and not in your DataModules.
Make sure there isn't any prompts for confirmation and operations that requires user input on DataModules code.
You should not use any global vars.
Hope this helps.
For automated construction of tests for DUnit, you could use OpenCTF, which is able to find all components and create test cases automatically at test run time. The example tests include some basic data access layer tests.
http://sourceforge.net/projects/openctf/
and
http://cc.embarcadero.com/Item/24136
alt text http://www.mikejustin.com/images/OpenCTF.gif
Related
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.
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.
i'm trying to learn how to properly setup testing for an ASP.Net MVC.
and from what i've been reading here and there thus far, the definition of legacy code kind of piques my interests, where it mentions that legacy codes are any codes without unit tests.
so i did my project in a hurry not having the time to properly setup unit tests for the app and i'm still learning how to properly do TDD and unit testing at the same time. then i came upon selenium IDE/RC and was using it to test on the browser end.
it was during that time too that i came upon the concept of integration testing, so from my understanding it seems that unit testing should be done to define the test and basic assumptions of each function, and if the function is dependent on something else, that something else needs to be mocked so that the tests is always singular and can be run fast.
Questions:
so am i right to say that the
project should have started with
unit test with proper mocks using
something like rhino mocks.
then anything else which requires
3rd party dll, database data access
etc to be done via integration
testing using selenium?
because i have a function which
calls a third party dll, i'm not
sure whether to write a unit test in
nunit to just instantiate the object
and pass it some dummy data which
breaks the mocking part to test it
or just cover that part in my
selenium integration testing when i
submit my forms and call the dll.
and for user acceptance tests, is it
safe to say we can just use selenium
again?
Am i missing something or is there a
better way/framework?
i'm trying to put in more tests for regression testing, and to ensure that nothing breaks when we put in new features. i also like the idea of TDD because it helps to better define the function, sort of like a meta documentation.
thanks!!
hope this question isn't too subjective because i need it for my case.
so am i right to say that the project should have started with unit
test with proper mocks using something
like rhino mocks.
The project should have started with a good separation of concerns. Once you have a good separation and you work with abstractions instead of concrete classes using a mocking framework and writing unit tests is a piece of cake.
then anything else which requires 3rd
party dll, database data access etc to
be done via integration testing using
selenium?
Yes.
because i have a function which calls
a third party dll, i'm not sure
whether to write a unit test in nunit
to just instantiate the object and
pass it some dummy data which breaks
the mocking part to test it or just
cover that part in my selenium
integration testing when i submit my
forms and call the dll.
You should not have a function that calls a third party DLL. You should write an abstraction/wrapper around this DLL which you would use and which will be mocked in the unit test where you will verify that your function calls the proper methods without really calling it. You would then use a DI framework in the application to do the plumbing.
and for user acceptance tests, is it
safe to say we can just use selenium
again?
Selenium or any other Web testing framework would be fine. In the more advanced ($) versions of Visual Studio you could write web tests.
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.
I'm implementing the Data Validation Validators as shown here:
http://www.asp.net/learn/mvc/tutorial-39-cs.aspx
This works great at runtime, but how can I Unit Test to verify if I say attribute [StringLength(10)], an error is returned?
Brad Wilson describes it pretty well in a blog post from a while ago (you'll have to scroll down a bit). Basically, you write tests where you use reflection to make sure that the proper attributes are applied, and then trust the framework to do its job on adding errors. After all, someone else tested the Data Annotation Validators before they were published - you just have to make sure you use them right =)
This post by Villecoder is the unit testing solution I'm using. It also allows you unit unit test custom annotations
http://villecoder.com/2010/04/23/unit-testing-custom-data-annotations/