I am quite new to fitnesse, I really like the ideas. But how do you do it in real life?
I have a solution that contains several dll projects in visual studio.
The projects use each other.
It's basically WPF projects so it should be relatively easy to make Fitnesse a new view that uses the viewmodels.
I think the solution here is to make a project for fitnesse, a.proj. that project will link to other assemblies that we make. lets say that b is where our business logic is and c, contains some lower level logic. In b I have my business class.
namespace b {
public class SomeBusinesslogic {
public C:SomeValue something;
public bool DoSomething(C:SomeOtherValue value1,C:Somevalue value2){
... somelogic ....
}
}
}
namespace c {
public class SomeValue{
public int a;
public int b;
}
public class SomeOtherValue{
public float c;
public string textd;
}
}
in my fitnesse wiki page how would I write the paths to include a.dll that is my fitness wrapping. and b.dll that is under test. And the c.dll that is also called through b.dll.
!path ..\xxx\bin\c.dll
!path ..\xxx\bin\b.dll
!path ..\xxx\bin\a.dll
or is there any smarter way of doing this?
thanks
See if this helps you get started http://www.asoftwarecraft.com/2011/07/starting-fitnesse-project-with-fitsharp.html
Try to use one path variable with comma-separated list.
Also there are different behaviours. FitSharp runner requires the list of the namespaces or classes which are defined in the configuration (see the project above). NetRunner plugin requires the dlls list in the path only. Then it will find all classes inherited from the BaseTestContainer class and add them to the functions containers list. Then it will union all these function to the one list and will use this list for test execution.
And important note for the configuration file: for the fitSharp you have to show the configuration file directly. For the NetRunner the configuration file will be used from the first library availble. So, for example you have this path variable:
!path a.dll, b.dll, c.dll, d.dll
b.dll and c.dll contains configuration, e.g. there is two existing files: b.dll.config and c.dll.config. And there are any configuration for the a.dll and d.dll. Then the b.dll.config will be used for the test domain.
Related
I am using same constants in two different project in different visual studio solutions.
Project 1 is ASP.NET WEB API and
Project 2 is client web application.
Constants example:
1. BUYING_RATE
2. THRESHOLD_LIMIT
etc
My question is.
Should I create a new library project just for handling constants and share this dll in both projects? I want to avoid
duplacate code in two different projects
Note 1: I cannot add both projects (API project and client project) in one solution due to some limitations so ignore this
Note 2: Both projects are managed by me
One more scenario is. ASP.NET WEB API will be consumed by 3rd parties as well. So should I provide the dll-s to them or API documentation is enough.
Or Am i thinking wrong about the design. If yes have a better solution, then what other options are to solve this problem
Thanks in advance
You can use a NuGet to share constants but I wouldn't. The main problem is that you will have to plan your constants beforehand or the NuGet publication will delay your progress.
When using a shared library, consider using variables instead of constants. It often happens that you need to change a constant value and you do not want to issue a full rebuild. Constant values are compiled into the assemblies referencing them. Variables get evaluated at run-time.
When making a shared library, consider providing a statically accessible instance container. It is often usable to provide different semi-constant value sets for different reader instances.
//Constant-provider assembly code. Separate library that is.
public class MyConstants
{
//Gets compiled into user code. Changing value -> rebuild all clients.
//public const double BUYING_RATE = 0.5;
//Gets evaluated in run-time. Changing value -> clients get new value.
public readonly double BUYING_RATE = 0.5;
private static MyConstants _default;
static MyConstants()
{
_default = new MyConstants();
}
//Provide default instance. You can change it in run-time when needed.
public static Default
{
get
{
return _default;
}
}
}
//Constant-user assembly code. Sample usage code for reader assemblier.
private class User
{
public void Method1()
{
... = MyConstants.Default.BUYING_RATE;
}
}
I had a simple implementation of MEF loading some dlls (plugins) from a directory. This was running well under MEF1 but now I want to use the same functionality with MEF2 and it gives me an IEnumerable that contains the right count of dlls that are in the directory but all the assemblies the same.
For example I have two assemblies: fakeplugin1.dll and fakeplugin2.dll in the directory. They exports FakePlugin1 and FakePlugin2 classes. Now when I call container.ComposeParts() I don't have anything in the list decorated with ImportMany and container.Catalog contains two assemblies in the directory but both of them are FakePlugin1.
Here's the code:
[ImportMany(typeof (IDCPlugin))]
IEnumerable<IDCPlugin> workplaceControllers;
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);
var agcatalogue = new AggregateCatalog(catalog);
var container = new CompositionContainer(agcatalogue);
container.ComposeParts();
I am trying to use ExportFactory and RegistrationBuilder but I've just realized that even the base functionality donesn't work as expected.
What am I doing wrong? Has something changed in MEF2 I should know? How to load the two different assemblies? :)
Thanks for your help in advance!
Edit:
It always creates two instances of the first type in the folder (ascending in abc). If I put an other one in the folder it creates three of the same, etc.
Edit:
I have uploaded code to pastebin that gives the same result with MEF2: http://pastebin.com/3fWcujPS
A catalog will contain Import and Export definitions for anything detected. Regardless of if you actually need it.
This is a 'feature' of MEF. You will need to either ImportMany and selectively filter the plugins you require.
So how do you handle multiple plugins gracefully? Try this:
[Export]
public class PluginService
{
public const string BEST_PLUGIN = "BestPlugin";
[ImportMany]
public IEnumerable<Plugin> Plugins{ private get; set; }
[Export(BEST_PLUGIN)]
public Plugin BestPlugin{ get { return GetBestPlugin(); } }
Plugin GetBestPlugin()
{
return Plugins.FirstOrDefault(); //or some other logic for selection
}
}
If your plugins are resource intensive, you may want to consider Lazy initialization.
Lazy<T, TMetadata> is a type provided by MEF to hold indirect
references to exports. Here, in addition to the exported object
itself, you also get export metadata, or information that describes
the exported object. Each Lazy<T, TMetadata> contains an IOperation
object, representing an actual operation, and an IOperationData
object, representing its metadata.
http://msdn.microsoft.com/en-us/library/dd460648.aspx#further_imports_and_importmany
MEF has strong rules on component cardinality (number of things) to ensure that there are never any surprises but this does mean you have to be careful with your deployment.
I am importing and exporting from the XPDL standard using C#.
I have written a hierarchy for classes using XPDL 2.1 and have debugged serialization with XmlSerializer. I need to implement XPDL 2.2.
The structure of the classes has changed. There are additional parameters as well. There was list of Artifacts which was child of the root class, but the newer version lost DataObject from all of Artifacts. The DataObjects moved from an additional List into WorkflowProcess.
I need to support XPDL 2.1 and XPDL 2.2. What is the best way to implement both of them?
I can see 3 ways:
Copy and paste existing hierarchy with needed fixes (it is awful!)
Create a base class and create two child classes. One for 2.1 and another for 2.2 (but will not it be too complex to maintain?)
Implement conditional serialization using an enum variable. The class will contain the super-set of 2.1 and 2.2 (This option seems overly complex)
Please let me know if there is a better approach.
Create two additional seperate projects in your solution. The first should contain classes to be parsed from XPDL 2.1.
The second one is for 2.2, it should include all cs files from first's project folder as links. Instead of managing them manually add these lines to your second project file:
<Compile Include="..\ParserXPDL21\Classes\**\*.cs">
<Link>Classes\file.cs</Link>
</Compile>
Remember to reload the second project each time you add or remove files from the first, otherwise Visual Studio will not compile it until you do.
For the second project declare a conditional constant in the project properties: XDPL22
Now you can modify the first project files like this to maintain two versions in the same file:
#if !XDPL22
namespace ParserXPDL21
#else
namespace ParserXPDL22
#endif
{
[Serializable]
public class Root
{
#if !XDPL22
public Artifact[] Artifacts { get; set; }
#endif
public int NormalProperty1 { get; set; }
public int NormalProperty2 { get; set; }
public int NormalProperty3 { get; set; }
}
}
After that you can reference these two projects from your main project and use the classes for the two different versions.
I know it doesn's seem to be a very elegant way but it helps when you have to make a lot of duplicated code.
You still need a way to check what version of XPDL you are going to read. May be you can just look at the file extension but if it's the same than you can just try to read 2.2 and if it throws an exception or the data is not correct think this is 2.1, or you can read XML manually with XmlReader and check before deserializing.
I have to be able to connect to two different versions of the an API (1.4 and 1.5), lets call it the Foo API. And my code that connects to the API and processes the results is substantially duplicated - the only difference is the data types returned from the two APIs. How can I refactor this to remove duplication?
In Foo14Connector.cs (my own class that calls the 1.4 API)
public class Foo14Connector
{
public void GetAllCustomers()
{
var _foo = new Foo14WebReference.FooService();
Foo14WebReference.customerEntity[] customers = _foo.getCustomerList;
foreach (Foo14WebReference.customerEntity customer in customers)
{
GetSingleCustomer(customer);
}
}
public void GetSingleCustomer(Foo14WebReference.customerEntity customer)
{
var id = customer.foo_id;
// etc
}
}
And in the almost exact duplicate class Foo15Connector.cs (my own class that calls the 1.5 API)
public class Foo15Connector
{
public void GetAllCustomers()
{
var _foo = new Foo15WebReference.FooService();
Foo15WebReference.customerEntity[] customers = _foo.getCustomerList;
foreach (Foo15WebReference.customerEntity customer in customers)
{
GetSingleCustomer(customer);
}
}
public void GetSingleCustomer(Foo15WebReference.customerEntity customer)
{
var id = customer.foo_id;
// etc
}
}
Note that I have to have two different connectors because one single method call (out of hundreds) on the API has a new parameter in 1.5.
Both classes Foo14WebReference.customerEntity and Foo15WebReference.customerEntity have identical properties.
If the connectors are in different projects, this is an easy situation to solve:
Add a new class file, call it ConnectorCommon and copy all of the common code, but with the namespaces removed. Make this class a partial class and rename the class (not the file) to something like Connector.
You will need to add a link to this to each project.
Next, remove all of the code from your current connector classes, rename the class (not necessarily the file) to the same as the partial class, and add a using statement that references the namespace.
This should get what you are looking for.
So, when you are done you will have:
File ConnectorCommon:
public partial class Connector
{
public void GetAllCustomers()
{
var _foo = new FooService();
customerEntity[] customers = _foo.getCustomerList;
foreach (customerEntity customer in customers)
{
GetSingleCustomer(customer);
}
}
public void GetSingleCustomer(customerEntity customer)
{
var id = customer.foo_id;
// etc
}
}
File Magento15Connector
using Foo15WebReference;
partial class Connector
{
}
File Magento14Connector
using Foo14WebReference;
partial class Connector
{
}
Update
This process can be a little confusing at first.
To clarify, you are sharing source code in a common file between two projects.
The actual classes are the specific classes with the namespaces in each project. You use the partial keyword to cause the common file to be combined with the actual project file (i.e. Magneto14) in each project to create the full class within that project at compile time.
The trickiest part is adding the common file to both projects.
To do this, select the Add Existing Item... menu in the second project, navigate to the common file and click the right-arrow next to the Add button.
From the dropdown menu, select Add as link. This will add a reference to the file to the second project. The source code will be included in both projects and any changes to the common file will be automatically available in both projects.
Update 2
I sometimes forget how easy VB makes tasks like this, since that is my ordinary programming environment.
In order to make this work in C#, there is one more trick that has to be employed: Conditional compilation symbols. It makes the start of the common code a little more verbose than I would like, but it still ensures that you can work with a single set of common code.
To employ this trick, add a conditional compilation symbol to each project (ensure that it is set for All Configurations). For example, in the Magento14 project, add Ver14 and in the Magento15 project add Ver15.
Then in the common file, replace the namespace with a structure similar to the following:
#if Ver14
using Magneto14;
namespace Magento14Project
#elif Ver15
using Magneto15;
namespace Magento15Project
#endif
This will ensure that the proper namespace and usings are included based on the project the common code is being compiled into.
Note that all common using statements should be retained in the common file (i.e., enough to get it to compile).
If the FooConnectors are not sealed and you are in control to create new instances, then you can derive your own connectors and implement interfaces at the same time. In c# you can implement members by simply inheriting them from a base class!
public IFooConnector {
void GetAllCustomers();
}
public MyFoo14Connector : Foo14Connector, IFooConnector
{
// No need to put any code in here!
}
and then
IFooConnector connector = new MyFoo14Connector();
connector.GetAllCustomers();
You should introduce an interface that is common to both of the implementations. If the projects are written in the same language and are in different projects, you can introduce a common project that both projects reference. You are then making a move towards having dependencies only on your interface which should allow you to swap in different implementations behind the scenes somewhere using inversion of control (google, dependency injection or service locator or factory pattern).
Difficulties for you could be:
1) Public static methods in the implementations are not able to be exposed staticly via an interface
2) Potentially have code in one implementation class ie Foo14Connector or Foo15Connector that doesnt make sense to put into a generic interface
I'm writing a simple plugin based program. I have an interface IPlugin which has some methods and functions, and a List<Plugin> in my main program. For the sake of simplicity, lets say its defined like this:
public interface IPlugin
{
public void OnKeyPressed(char key);
}
Everytime a key is pressed, I loop through the Plugin list, and call OnKeyPressed(c) on each of them.
I can create a class like so, and add it to the list...
public class PrintPlugin
{
public void OnKeyPressed(char key)
{
Console.WriteLine(c);
}
}
And then whenever you press a key, its printed out. But I want to be able to load plugins from DLL files. This link was helpful, but it doesn't explain how to have the classes in the DLL implement my IPlugin interface... How can I do that? I really don't want to have to copy the IPlugin.cs file every time I want to make a plugin...
If I am understanding you correctly...
Create 3 Projects:
Project 1: Your main program (the one with List in it)
Project 2: the project with your interface
public interface IPlugin
{
public void OnKeyPressed(char key);
}
Project 3: A sample Plugin
public class PrintPlugin : IPlugin
{
public void OnKeyPressed(char key)
{
Console.WriteLine(c);
}
}
Then Add project 2 as a reference to both project 1 and 3.
This way you share the interface with both your main project and any of your plugins.
I have used this on a couple of projects and it has served me well.
You may want to look into the Managed Extensibility Framework as well. It provide a complete API for writing plugin based programs and covers a lot of concerns such as security if you're ever going to plan to make the plugin API available to third parties.
If you need to load user defined plugins, you should search for new DLLs when the application starts (or any other action). This can be done by using:
1) AppDomain.CurrentDomain.GetAssemblies() method returns the list of loaded assemblies in the current AppDomain
2) Search all DLLs in a folder where plugins should be positioned and check if a certain assembly is in the list. If not, use the Assembly.Load method to load this assembly, find the IPlugin class in it and finally add it to the List object.