How do you properly test the view in MVVM? - c#

I've seen a few articles on unit testing view models in MVVM and how the tests themselves are consumers of the view models, testing the functionality of the viewModel and model. However, I'm left wondering how I go about testing the views (UI) to ensure they are wired up to my view models properly. I don't want to write a test that, for instance, presses a button to make sure something is written to the db as this is effectively testing my VM, which i've already done.
For instance, I'd like to be able to write a test to make sure that a button is wired up to a specific command. Therefore preventing anyone from coming along and removing the button's command, making it no longer functional.
Is this possible? thanks.

But what if someone (hopefully a designer) wants to change the Button to a MenuItem? Your test will break and you'll have to fix it. One of the major boons of MVVM is that designers can really be free to arrange and rearrange the interface however they like without requiring too much back-and-forth with the developers. Writing unit tests against the UI annuls that boon.
I'm kind of playing Devil's advocate here. I'm not saying testing the UI is completely useless and never has a place in anyone's code base. What I'm saying is that the returns are diminishing, and that you may be trading one problem for another.
As for how you actually test a view in "isolation" . . . the easiest way I think would be to use view models with injected mock services. Your view models can use a service locator to grab dependent services, so your unit tests can inject dummy services. You could then use a combination of named-element references, visual tree crawling, and the WPF UI automation APIs to assert that different visual elements have properties set as expected.

I think there is something from Telerik (Art of test) which can help automate the raw UI.
http://www.artoftest.com/products/webaii.aspx
Though now I have looked it up that is Silverlight rather than WPF. Hopefully its a good starting point at least.

Related

What exactly am I using?

Sorry for the vague title. I am pretty ashamed to ask this but I really need my awareness right now. I cannot identify whether I am following an MVC pattern or MVVM pattern.
In my previous internship, we had C# code (.NET) which had a controller and connected directly to the database (there wasn't a service layer). The controller would fetch information, format into JSON and give it to Angular's controller, which would display it on the view.
In my current internship, we don't use Angular. We use .cshtml files. The service layer provides its information to the controller, which formats the MODEL and gives it to the .cshtml view and which displays the content.
My questions:
Which one is MVC and which one is MVVM? Please drop down to my level and explain. Most of what I've read on the web seems to confuse me more with what I observe at work.
Everyone at work calls both of them MVC and, I am really confused now. If both are MVC, what's the difference between the two?
Angular is definitely more Model-View-ViewModel-ish. Whereas what you're doing now definitely sounds like MVC.
MVVM is a special pattern where the UI state is encapsulated in a ViewModel, so that the rendering of the final UI is fairly dumb and just data-binding. The state logic to say, show this button, or hide this area is all encapsulated in the ViewModel. One benefit, is that this allows for unit tests to be built to test the ViewModel and thereby implicitly testing all of the UI behaviors. (see: Wikipedia article on MVVM and Martin Fowler's Introduction to Presentation Model which MVVM is a variation of.)
In MVC, the view itself has the latitude to control it's behaviors, what you want to show/hide, etc based off of the data provided, the model. This means that in MVC, you can't test the UI behaviors (e.g. if something is correctly showing or hiding based on data changes) without testing the UI itself.
So in summary, MVVM, the ViewModel controls the UI behavior and the UI itself is dumb and just uses data-binding and does what it's told to do based on the logic in the ViewModel.
In MVC, the UI is 'intelligent' and re-shapes and renders itself however it feels it needs to based on the data it receives from the model.
You can basically look at how the UI is rendered and if you see the UI rendering logic making a lot of its own decisions about how to render itself based on the decision, then you pretty much know you're using MVC. If you just see a lot of data-binding, where almost every behavior is driven by a separate class that encapsulates all of the logic for showing and hiding pieces of the UI and this data is passed to the UI via data-binding, then it's probably MVVM.
I hope that helps.
In both cases, you are using MVC (or at least an MVC-ish pattern). When using the .cshtml files, you are using server-side MVC. When using Angular, you are using client-side MVC (which is probably more like MVVM). The biggest difference is where the model is rendered into HTML elements; on the client, or on the server.
In my opinion, this is a better way to view the differences in what you have done.

WPF MVVM Code Behind

I try to avoid code behind in views, within my WPF MVVM project.
However I have some things that are very specific to the view. For example when a control gets focus I want the full text to be highlighted (even if a user clicks into the text box).
Here I have a choice to handle this in the view model (which would then need to know about the view, which I want to avoid).
I also have some other code like that does things to the UI when the user presses up down left or right on the keyboard (and they only make changes to the view, not the model or viewmodel) and again I'm thinking the best place for these is in the code behind of the view.
So I'm asking if the code only affects the view (e.g. things like cursor movement, selecting all text in a text box etc..., and not the model or view model, is it okay to put it in code behind, rather than elsewhere.
Wondering what is best practise here, or if anyone else has a better suggestion where to put this code.
So I'm asking if the code only affects the view (e.g. things like
cursor movement, selecting all text in a text box etc..., and not the
model or view model, is it okay to put it in code behind, rather than
elsewhere.
Not only it is OK, but it is strongly encouraged.
MVVM is not here for you to write thousands of ugly lines of code in ViewModels, it's here to make the code testable and to introduce a separation of concerns.
If it's purely related to the view (your "focus" example is a perfect example), then just write it in the code behind.
If the behavior is UI related only, then you should not put it in the ViewModel. The highlighting example you gave is a good example of such a case. Having said that, I would suggest you avoid repeating your code by (for example) creating a custom control that highlights the text when it has the focus. This way, you can reuse the control in as many views as you can, your views stay free of codebehind, and if you optimize your control, the optimizations happen across the board.
EDIT:
In light of Ravi's answer, Behaviors are also a way to introduce UI related logic while leaving the View free of codebehind. However, if you are finding yourself repeatedly declaring the same controls with the same behaviors, in my opinion it is better to create a control that incorporates the behavior.
That being said, if said UI logic is going to appear only once in one view, you may consider putting it in codebehind. Although it is quite rare to know in advance that you are not going to need that logic elsewhere.
EDIT:
I think #ken2k 's use of strong encouragement refers to not putting it in the ViewModel, which I also advocate. UI logic should be implemented in the View, as he says. Now, there are a few ways of doing that. One of these is coding it directly in your codebehind, which can lead to repetitious code and maintenance issues. Also, if you employ unit testing, it could put you in a difficult spot. The second is coding such logic into behaviors, which is a good way to encapsulate UI code. You can then unit test the behavior to make sure it works OK. However, you can find (as I did, in many projects) that you have started to pepper every TextBox in your XAML's with behavior tags. If that starts to happen, I would (and have) create a 'HighlightedTextBox' control and use that in my XAML. In summary, my suggestion does not contradict ken2k's, but is a pointer in the direction of resolving some issues you may have when placing logic for your View.
Using Custom controls as #Boluc Papuccuoglu suggested, is good option but before using that i want you to take look here Behaviors in WPF introduction
It is strongly recommended to have all your view stuff logic at one place. Instead of polluting ViewModel you should always keep View stuffs in XAML and code behind.
ViewModel responsibility is to contain only data part which can be unit tested. With UI stuff in ViewModel, you will make it hard to be unit tested.
As per link here at MSDN, definition of code behind:
Code-behind is a term used to describe the code that is joined with
markup-defined objects, when a XAML page is markup-compiled.
As you can see, code behind is partial class of your view. One half is declared via x:Class attribute at root element and other half in form of code behind. So, as per me all UI stuff should be at one place and you should not think twice before placing the view stuff in code behind. (that's what it is meant for). MVVM never meant design without any code behind.
Also ViewModel responsibility is to just provide data to your view via data binding. It should never be aware of UI stuff.
Read more about it here - Code behind and XAML in WPF.
How much of your code do you want to unit test? If your view can trigger a command when a control gets focus and your view model can programatically fire an event to highlight the text in that control then you have everything you need to unit test that behaviour with mocked objects. And even if you don't want to unit test (or can't because the bean-counters at your company won't give you the time/budget to do so) then placing that functionality in attached behaviours means they can be used elsewhere. I'm not quite the hard-core MVVM purist as some others on this site but I can honestly say that even in the largest enterprise applications I've worked on I've never once seen a case where WPF code-behind was absolutely required.

Unit testing with and without private Accessor

Are there any disadvantages in using a private accessor to test a piece of code?
I'm weighing the option of using a private accessor only to test my GUI, as opposed the the methods/properties that are publically exposed.
This will allow some GUI testing i need, i just wanted to make sure their were not any hidden "pitfalls" in using a private accessor in how it behaves.
So to recap, your stated goal is:
I'm weighing the option of using a private accessor only to test my GUI... This will allow some GUI testing i need...
In short, yes there are pitfalls. The code you are testing is still tightly coupled to the user interface.
In the comments you clarify your goal/problem as:
What about in the case if i want to test, Drag/drop. Custom Controls, Overriden events?
All I can say is welcome aboard. The software industry has struggled with this for nearly half a century. The fact remains that testing UI is hard, Really HARD. Yes you can take a piece of code that is tightly coupled with a UI element and try and automate it; however, your going to be fighting tooth-and-nail to make headway against poor assumptions.
The 'trick' to testable UI is not to make your UI testable, but to remove the code you want to test from the UI. Thus the wide acceptance of N-Tier application development and presentation design patterns like MVC, MVVM, etc.
see the following:
Model View Controller
Model View ViewModel
Model–view–adapter
Model–view–presenter
The primary goal or driving force behind many of these design patterns is to remove the tight coupling between behavior and presentation. This enables you to then test a behavior like drag-n-drop without a user interface. My recommendation is review the patterns, choose one you like, and then start refactoring the code as you write your unit tests.
Another way to think of writing UI for testing is to remove every if, else, for, while, switch, or other control statement from your user interface code. The resulting 'shell' of a UI should be very resilient to change. Just be careful when using things like data binding that rely on reflection (which is generally an acceptable practice). The primary downside to this is that the compiler can not tell you that a member no longer exists.
Updated
#timmy you wrote:
... for example if i want to test mouse click behavior...
So what about the mouse click behavior cannot be moved to a controller rather than being embedded into the form? I guess the "Close" button might have a problem, but beyond that why not move the logic to another class that can then be tested?
BTW, You don't have to pick just one pattern MVC, MVVM, etc, they are 'guidelines' or 'suggestions' not hard rules so don't get ridiculous with it. Just try and make the logic separate from the UI and independently testable. As an example, perhaps your "Click" event fits better with a simple command class? Using a command pattern is easy, new up an object and execute it. Consider this example code for a folder copy form:
private void OnCopyClick(object sender, EventArgs args)
{
var cmd = new MyCopyCommand(this.FolderPath, this.txtTargetFolderPath.Text);
new ErrorHandler(this).Perform(cmd);
}
This works well, it has no 'real' logic other than what to provide the command and has no conditional code paths. Notice we don't even directly invoke the command but rather defer that to someone who can handle an error appropriately. Usually this 'ErrorHandler' would be provided to the Form rather than constructed directly, but you get the idea.
From this we should be easily able to verify the correct behavior of the MyCopyCommand. In the end you should wind up with a bunch of "flat functions" in the UI, ie. functions that have no nesting or curly braces. Of course this is a rule of thumb, not to be taken to such an extreme as to prevent you from being productive.
I know this may seem like a lot of work, but truthfully it is not when you are already working to write a set of tests. You can be productive AND write solid code. You just need to know when to cheat, and when not to. That comes with experience and after 20 years, 10 of those writing NUnits, I still fail once in a while. When something breaks because you didn't do this, first extract the logic from the UI, then write a unit test to prove it's broken, then fix it.
It's better not to use them, instead try to find out if you can inject any dependency. Unless you're working on a legacy code where you want to create some unit tests using private accessors, I'd suggest not to use them and even in this case, I'd recommend you do that temporarily until you refactor legacy code.
In addition to what AD.NET said.
I could use those private properties in tests only until I finish my refactoring (to Model View Controller, Model View Presenter, Model View ViewModel) so that I don't have to test GUI at all!

Testing ASP.NET Webpages without using [HostType("ASP.NET")]

So I'm trying to get productive practicing TDD in a ASP.NET webpages project, and launching a server every time I want to run my tests, well it isn't quite fast.
So I'm trying to find a way to do my testing without the use of the [HostType("ASP.NET")] attribute, but there is always some error.
We're using App_GlobalResources folder for our resource files, and this is one of the problems; when removing the attributes, just keeping the [TestMethod] (using MStest), it can't find the resources. So I'm !NOTE assuming, that it's not able to find the resources assembly.
So, has anyone done this before? Any experiences?
And comments saying "why don't you just convert to MVC", well it's just to big an app and to little time. Maybe it'll happen in a couple of years, maybe more, maybe never.
My experience testing ASP.NET Web apps has been painful (which looks like yours is too!) Resisting MVC Comment
My best advice would be take little steps each time you touch an area to make it more testable. For example, for any bits of code you can pull out to it's own assembly that you can reference do so.
First candidate would be you resource files. Then your tests could reference that satellite assembly without the "App_" hoops to jump through.
The approach I took involved creating a presenter class for each page. You create an interface that the page implements with methods & properties that the presenter needs to control the UI. All your logic goes in the presenter, along with a reference to the interface. the page references the presenter and passes itself in.
The benefits you get are the page now should only contain code to make the UI work. The presenter does most of the work. Because it can access the UI, via the interface it can control the UI. Because the access is via an interface, you can test the presenter using a mocked UI.
I found my pages were vastly simplified, with much greater differentiation between code to support the logic of the app & code to make the UI work. It also made it simpler to introduce service classes & IoC which is not always the easiest with webforms.

MVP and presenter granularity

We've been using the MVP pattern and Winforms with a fair amount of success. However, a question always pops-up about MVP:
What is a good granularity for presenters?
What I mean by that is: With Winforms, a fine-granularity usually works quite well for user controls. That way, it's easy to reuse user controls and use them as building blocks while designing more complex GUIs. However, having the same (fine-)granularity with presenters seems to be a problem.
On one hand, having coarse-grained presenters hinders the ability to use "plug-in" controls and it sorts of violate the DRY principle: Multiple presenters often need to implement the same logic (populate a list of customers, for instance), which is used by multiple, more complex, controls.
On the other hand, fine-grained presenters seem to limit the ability to reuse controls in different situations. For instance, an editing view might sometimes need to save the customer right away; sometimes it needs to link it to something else; sometimes is just needs to validate it; and so on. It often depends on the more complex control. But there's also a fair amount of shared behaviour.
Note that, in both cases, 1-presenter-1-view is achievable. What is considered "1-view" changes.
What is usually considered best-practices for presenter granularity using MVP and Winforms?
Fine-grained presenters and customizable behaviour through options or something of that nature?
Coarse-grained presenters and low presenter reusability?
Something else?
Disclaimer: We mainly use Supervising Controller but I think it also applies to Passive View. Sorry for the long question, too.
We use MVP at all of our clients and this is definitely a conversation that comes up in more than one occasion. How clean should our code behind classes and presenters be? Having said that, we have chosen to use the coarse-grained presenter approach. Basically, every form would have its own presenter and would only get and set properties of any of the controls on a particular form using its view. Populating controls-a call to a db to populate a combobox for example-is located in a public service class. Any validation of user inputted data is located in a BO class which can be reused by any and/or all of the presenters. I hope this helps.
In my CAD-CAM system my presenters don't use user controls. User controls reside in the view which reside in a EXE assembly that implement the view interfaces the presenter use.
If want to display a list of customers I hand it off to the view which has a DisplayCustomerList and it uses whatever combination of user controls it needs to display the customer list. If multiple views show the customer list in the same way then in the ExE/View assembly they share a user control or class for doing that. That class doesn't go outside of that assembly.
Our software is adapted to run many different types of metal cutting machine. So we place a lot of emphasis on being able to rip off the UI and replace it with a completely different UI (corresponding to a different machine). All of these UIs reference the same set of core assemblies.
The hierarchy looks like this
View EXE
Presenter Implementation
Command Assembly - commands are executed by the presenter that modify the model
Presenter Interfaces
Model Assemblies
Off to the side are loadable assemblies that define dynamic content like what file types can be loaded, reports, cutting device drivers, etc. These implement various interfaces found in the model assemblies
One thing I do is that I don't impelment a view presenter for every dialog. If the dialog is tightly bound with a command then it is defined, created, and used along side the command class. Occasionally a group of related commands will share a dialog (File handling for example).
The essential question I ask when using MVP is "What happens if want to completely replace the forms with something else?". The answers to that question will identify where you are too dependent on a particular user control or form engine.
The biggest problem (and one that I haven't got a good answer for) of my setup is that current IDEs and langauges make it very easy to tie user controls to database records. It is so productive compared any other setup it tends to dominate the design. I haven't had to deal with the issue much in my CAD-CAM application so I don't have any answer other than passing the dataset to the view and let it handle it. This site has some patterns that may be of use in this situation.

Categories

Resources