Running NUnit tests on different configuration - c#

I'm new to .Net and hence don't know if the approach which I'm following below is correct or is there any better way to do it. Can someone please suggest ?
I want to keep different set of configuration for different environments (DEV,QA, UAT, etc) and based on user input load that environment config and start my Nunit tests.
I'm planning to create a different resource file for each of these for ex - QA.resx, DEV.resx, etc and then just load specific resource file based on user input.
for ex.
QA.resx will have
hostname=sample.qa.com
port=1234
DEV.resx will have
hostname=sample.dev.com
port=4321
And then at runtime if I specify something like env=DEV then it should load configuration from DEV.resx and start running the test cases.
Is this a good approach ?

Is this a good approach ?
I don't think so.
First of all, your Unit Test should not depend on environment you're using. True Unit Test should not have any external dependency, like database, file system, external services, etc. Thus UT execution should be the same no matter whether it's launched on a developer workstation or CI server.
If your application requires different configurations for different environments (it's a very common case), the best choice is to use config transformations. Check this article for details.

Related

Execute Coded UI Tests in multiple environments

Right now my Coded UI Tests use their app.config to determine the domain they execute in, which has a 1-1 relationship with environment. To simplify it:
www.test.com
www.UAT.com
www.prod.com
and in App.config I have something like:
<configuration>
<appSettings>
<add key="EnvironmentURLMod" value ="test"/>
and to run the test in a different environment, I manually change the value between runs. For instance the I open the browser like this:
browserWindow.NavigateToUrl(new Uri("http://www."
+ ConfigurationManager.AppSettings.Get("EnvironmentURLMod")
+ ".com"));
Clearly this is inelegant. I suppose I had a vision where we'd drop in a new app.config for each run, but as a spoiler this test will be run in ~10 environments, not 3, and which environments it may run may change.
I know I could decouple these environment URL modifications to yet another XML file, and make the tests access them sequentially in a data-driven scenario. But even this seems like it's not quite what I need, since if one environment fails then the whole test collapses. I've seen Environment Variables as a suggestion, but this would require creating a test agent for each environment, modifying their registries, and running the tests on each of them. If that's what it takes then sure, but it seems like an enormous amount of VM bandwidth to be used for what's a collection of strings.
In an ideal world, I would like to tie these URL mods to something like Test Settings, MTM environments, or builds. I want to execute the suite of tests for each domain and report separately.
In short, what's the best way to parameterize these tests? Is there a way that doesn't involve queuing new builds, or dropping config files? Is Data Driven Testing the answer? Have I structured my solution incorrectly? This seems like it should be such a common scenario, yet my googling doesn't quite get me there.
Any and all help appreciated.
The answer here is data driven testing, and unfortunately there's no total silver bullet even if there's a "Better than most" option.
Using any data source lets you iterate through a test in multiple environments (or any other variable you can think of) and essentially return 3 different test results - one for each permutation or data row. However you'll have to update your assertions to show which environment you're currently executing in, as the test results only show "Data Row 0" or something similar by default. If the test passes, you'll get no clue as to what's actually in the data row for the successful run, unless you embed this information in the action log! I'm lucky that my use case does this automatically since I'm just using a URL mod, but other people may need to do that on their own.
To allow on-the-fly changing of what environments we're testing in, we chose to use a TestCase data source. This has a lot of flexibility - potentially more than using a database or XML for instance - but it comes with its own downsides. Like all data driven scenarios, you have to essentially "Hard Code" the test case ID into the decorator above your test method (Because it's considered a property). I was hoping we could drop an app.config into the build drop location when we wanted to change which test case we used, at least, but it looks like instead we're going to have to do a find + replace across a solution instead.
If anyone knows of a better way to decouple the test ID or any other part of the connection string from the code, I'll give you an answer here. For anyone else, you can find more information on MSDN.

Specflow / automated testing - making directories inaccessible

So we're using C#/Specflow, and I have a test that reads
Given The publish directory can not be accessed
The app being tested reads/writes files from a directory, firstly checking it exists and if not throws an exception. I am testing that this exception is thrown. What I need to do is make the directory inaccessible for the duration of the test.
The options as I see it are:
Change the directory it's accessing by overriding it's config (Windows registry) for the duration of the test.
Rename the directory it's accessing for the duration of the test.
Change the permissions on the directory for the duration of the test.
None of these seem ideal, I'd like to leave the test server alone if possible. Can anyone tell me of a better solution to this please?
An option that you didn't specify is to mock out the file access behind an interface and then have the mock simulate lack of access.
This has the benefit of not needing to change anything for the test, but means that its not longer an integration tests. If you don't mock and instead change the config/folder access then this test will need to ensure it isn't run when any other tests are running as they might consequently fail due to those changes.
This question has an example of how you might do this simply, and also links this library and this library which might be able to help.

Best way to store settings (special requirements)

I found a lot of information for saving different kinds of application/user settings in different places but getting confused what could be the best way for me.
My problem has different dimensions:
The application will have some User-Roles (Admin, StandardUser, ...), where every User (based on Windows-Logon) will belong to one role.
The Admin is allowed to setup everything for everyone.
The settings have different categories:
Application settings (should be the same for every user on the computer)
User-Role-specific settings
User-specific settings
The application has several projects where different projects have to access the settings.
(4. The application is written in C#)
I don't want to mention the things that I have read because I don't want to steer your thoughts into a (maybe wrong) direction.
So, how would you handle this scenario?
Thanks a lot!!
Joerg
EDIT 1
Some more things after the first answers that I hope can clarify my question:
my question doesn't focus on the authentication of the users, it focusses on create/edit/save settings
my first attempts for solving the problem were:
using the Visual Studio Settings.Settings file
... doesn't work because I have several projects that have to have access to the settings AND I couldn't find a way to make the ApplicationSettings writeable (they are readonly)
use the ConfigurationManager-Class
... I am not experienced with this one but as far as I understand this class it is just another class that gives me access to my ApplicationSettings (and has the same problems like #1)
... maybe a link to a good tutorial will help
invent something on my own
... I still hope to find something ready-to-use
I guess in this kind of scenarios you probably have a database. When you incorporate users, user rights, etc in there it is probably also a good place to save your application settings.
I always love the database centric solutions, since there are widely available (when you want to create a new UI based on the same system, you can reuse the settings there).
I think the entity–attribute–value model is a good design strategy to consider.
You can create a view with triggers on them hiding system only properties, enabling the admin to change all, and the user to only change theirs.
By your description I'd say you want Role Based Authentication. It's something that has been asked before. I'd go to the link specified in that answer to find an overview and some code samples of how to approach this problem.
Microsoft has done a great job adding some abstractions with the Membership Providers and now the ASP.NET Identity Framework (in case you have a Web Application). Regardless of what you choose to do, database or config files are going to be involved (take a look here to learn how to manage those) and some sort of claim derived system.
Assumption: You already have figured out how you are going to handle roles, and your question is only about storage/retrieval of settings.
Point #3 means you can't use a Settings file for Application and User scoped settings combined with a custom configuration section for holding the role specific settings (optionally encrypted).
My next suggestion would be a WCF endpoint that exposes the settings, either in their entirety (security trimmed contents of Application + User specific + Role specific) or by some sort of dictionary lookup equivalent. Additionally:
The endpoint would need to require Windows Authentication (or possibly Claims) so that it could determine the user specific/role specific part.
Each application would then need to have knowledge of the WCF endpoint, either through configuration or potentially through WCF Discovery.
Update:
Note that WCF doesn't solve your storage question, but it helps with your point #3 - multiple projects that need to use the same settings. A WCF endpoint allows a single project that encapsulates the storage/retrieval of settings to be re-used by multiple clients. WCF can be complicated to read about, but in practice it's pretty easy to setup - you just decorate an interface and host it in IIS. You could also host it yourself in something like a windows service if you were adverse to using IIS, but deploying it to IIS would be a lot easier. You can then consume it in your other applications by adding a Service Reference to your project, and then you call the interface code as if the code was in your own project.
In case you are talking about a single application with multiple class libraries:
What I'm describing above assumes you are making multiple applications that all need to share settings. If you are actually talking about a single application with multiple class library projects, the built-in Settings can still be used - there is just one manual step you need to do to make it work across projects. After adding settings to both your application project and your class library project(s), you should copy the app.config section containing the settings in your class library and copy/paste it into your application's app.config. Visual Studio isn't very clever and it will only sync the class library Settings changes to an app.config within the class library project, even though an app.config for a class library isn't a "real thing", since only the app.config for the application consuming the class library is actually used by default (which is why you need to merge it into your application's app.config).
If you need multiple class libraries (including the main application project) to use the same settings, you could make a dedicated class library project just to hold the settings (note you can add multiple Settings files to this project to make the settings more modular), and then all the other projects could reference the common settings project (to avoid circular dependencies, you wouldn't hold any Settings in the main application project that a class library needed).
Overriding a user's settings
The Settings object has a mechanism you could use to override settings (say, with value's specified by an administrator). When you add a Settings object to your project, it creates a Settings partial class with some example code for wiring into the SettingsLoaded event. In this event, you could load your administrative settings (either through a WCF call, or perhaps from a know location on the file system) and apply any overrides.

Maintaining and Deploying Two Versions of an Application Simultaneously

I have a C# WinForms application in Visual Studio 2010 that is used by two different customers. The basic functionality of the application is the same for each customer, but certain lines of code (names of stored procedures, resources, certain behaviors) are different between versions. So far, I have kept the application in the same project, and used preprocessor directives when building/publishing to switch between which deployment to use. However, the scope of the project has grown to a point where this is no longer feasible.
Since so much of the code is shared, I'm trying to avoid duplicating source code files. I'm wondering what the best approach is to maintaining an application that requires different versions to be deployed simultaneously.
Use interfaces to define your classes. Having an interface means that you can have multiple implementations of the same interface, one for each of the clients. This will require you to analyze your existing codebase and identify logical separations in your code where these interfaces can be defined.
You then have the ability to load an interface as needed based on the client. You could, for example, do this via configuration. Based on a configuration value you load Implementation1 or Implementation2. There are many, many ways to accomplish this particular bit. You should read up on dependency injection, inversion of control and have a look at tools like Ninject, Autofac, Unity.
It may actually be difficult at first considering how you have been using preprocessor directives but seeing as how your application is growing, you will need this refactoring to happen. Keep in mind that if you do not do it now, this refactoring will be a lot more expensive later as your application becomes more complex.
The different functionality should be a part of the application's architecture. If you need different functionality for different customers, abstract it away - create an interface that wraps up the behaviour, then implement it in two different ways in two different assemblies. Then (depending on your deployment mechanism), you can ship your app with either one DLL or the other. To avoid having to recompile, add references, etc, you can use Dependency Injection frameworks such as Ninject, Castle Windsor, MEF etc. That's a "plugin-like" architecture, if code is sufficiently different.
If you're talking about text, colours, basic differences, they should simply not be hard coded but instead data-driven. If your app is internet-connected, it could download the appropriate settings when the user logs in. Else, something to indicate the text/colours/behaviour could be put in a config file specific to the customer. You can use config transforms to simplify that process.
You might be able to separate some of the differences by using resource, configuration, or property files of some kind. By this, I mean you store some kind of value in the file, such as the name of the stored procedure to use in a particular situation. Then your code reads the name from the file and runs it. You can change the values in the file without needing to rebuild your code for each deployment.

Changing winform app for specific clients

I have a winforms app. I give it to three clients and each one wants a small tweak or customization specific just to them. To accomplish this, I'd have to keep a separate version just for each client. I may wind up having many versions doing it this way. I thought dependency injection would be how to handle this but I hear you have to register your dependencies in the main method and you'd still have to add a reference to each clients DLL so I'd still need different versions. What is the preferred object oriented way to handle this? Any better ways to handle this?
You can use a Plug-in patten to load assembly at runtime: (from link)
Separated Interface (476) is often used when application code runs in multiple runtime environments, each requiring different implementations of particular behavior.
Most DI frameworks provide this functionality. You can search at get lots of Examples for framework you choose - if you don't want to roll your own.
Ninject
MEF
You can use a configuration file to configure your DI container, so that you can reuse the same binaries with different configuration files to implement the different customizations. But you need to be sure that you thoroughly test all of your different configurations. Slightly different versions of the same application are not trivial to maintain without causing unanticipated breaks.
Depending on the nature of the customixations, you might be able to capture all relevant modifications into a distinct part of the project (as opposed to keeping them spread all-over the project). If you can (e.g. a filering functionality is provided by the client), you can then load a DLL dynamically (e.g. based on a config file) and allow the functions in the DLL to perform the necessary functionality that accomplishes the customization (based on parameters provided by the main code).
This way you provide pre-defined hooks to your code that can be changed dynamically (even if only to load the dlls at startup time) as per the need of the client. You can separate these DLLs into multiple ones if there are distinct features that the clients want to change, but not necessarily all of the clinets all of the features. Then you can provide a "default" version of the DLLs.
Who develops the hooks is dependent on your setup with the clients.
Make sure you provide adequate documentation on how these hooks supposed to work -- even if you end up developing them.

Categories

Resources