have created a ProdIgnoreAttribute which extends from IgnoreAttribute. And I have assigned this attribute to certain tests which I want to run in DEV/QA but not in PROD.
ApplyToTest(Test test) method is not being called in this case. How to resolve this?
public class ProdIgnoreAttribute : IgnoreAttribute
{
private string IgnoreReason { get; }
public ProdIgnoreAttribute(string reason) : base(reason)
{
IgnoreReason = reason;
}
public new void ApplyToTest(Test test)
{
if (test.RunState == RunState.NotRunnable)
return;
if (StaticInfoHelper.VrCurrentEnv == (int)RunEnv.PROD)
{
test.RunState = RunState.Ignored;
test.Properties.Set("_SKIPREASON", (object)IgnoreReason);
}
else
{
base.ApplyToTest(test);
}
}
}
How about extending Attribute rather than IgnoreAttribute?
public class ProdIgnoreAttribute : Attribute, ITestAction
{
public void BeforeTest(TestDetails details)
{
bool ignore = StaticInfoHelper.VrCurrentEnv == (int)RunEnv.PROD;
if (ignore)
Assert.Ignore("Test ignored during Prod runs");
}
//stub out rest of interface
}
If you want a custom ignore message you could make a ProdIgnoreAttribute constructor that accepts a string. You'd then use the attribute on tests like: [ProdIgnore("ignored because xyz")]
Related
Based on https://gigi.nullneuron.net/gigilabs/data-driven-tests-with-nunit/ website. I have try to create a simple testcase which prepare for read data in the future. But I have no idea how to handle Argument and use it properly
I have try to set as a object, but i think this might not be a correct solution
[TestCaseSource("GetDataString")]
public void TestMethod2(object configs)
{
}
Here is source code
namespace SAP
{
[TestFixture]
public class Scenario1
{
// This one Give System.ArgumentException
[TestCaseSource("GetDataString")]
public void TestMethod(List<Config> configs)
{
Console.WriteLine("Config " + configs);
}
// This one can handle an Exception
[TestCaseSource("GetDataString")]
public void TestMethod2(object configs)
{
}
public static List<Config> GetDataString()
{
var datas = new List<Config>();
datas.Add(new Config("Nick", "Coldson"));
return datas;
}
}
public class Config
{
public string NickName { get; set; }
public string Name { get; set; }
public Config(string nickname, string name)
{
NickName = nickname;
Name = name;
}
}
}
Here is error msg
System.ArgumentException : Object of type 'SAP.Config' cannot be
converted to type 'System.Collections.Generic.List`1[SAP.Config]'.
The testcasesource has slightly different definition pattern. Assuming you use nunit 3 it should be:
[TestCaseSource(typeof(MyTestData), nameof(GetDataString))]
public void TestMethod2(List<Config> configs)
{
...
}
public class MyTestData
{
public static IEnumerable GetDataString()
{
var datas = new List<Config>();
datas.Add(new Config("Nick", "Coldson"));
return new TestCaseData(datas);
}
}
For more info, check the documentation:
https://github.com/nunit/docs/wiki/TestCaseData
Your GetDataString returns a List<Config>.
Meaning, your test method with a [TestCaseSource("GetDataString")] will be executed as many times as many items the list has and your method must match the item type.
//// This one throws System.ArgumentException
//[TestCaseSource("GetDataString")]
//public void TestMethod(List<Config> configs)
//{
// Console.WriteLine("Config " + configs);
//}
// This one is ok
[TestCaseSource("GetDataString")]
public void TestMethod(Config config)
{
Console.WriteLine(config);
}
If you need to get List<Config> instances in your test, then your source must return some collection containing list items.
I have sample object model as below.
[AttributeUsage(AttributeTargets.Method)]
public sealed class CandidateApiForMenuItem : Attribute
{
public CandidateApiForMenuItem(string caption)
{
this.Caption = caption;
}
public string Caption { get; set; }
}
public class FormDataElementBase
{
public FormDataElementBase()
{
}
[CandidateApiForMenuItem("Add PanelGroup")]
public void AddPanelGroup()
{
///...
}
[CandidateApiForMenuItem("Add BoxGroup")]
public void AddBoxGroup()
{
///...
}
[CandidateApiForMenuItem("Remove")]
public void Remove()
{
///...
}
public void GenerateGroupPopupMenuItems()
{
foreach (MethodInfo methodInfo in this.GetType().GetMethods())
{
if (methodInfo.GetCustomAttribute(typeof(CandidateApiForMenuItem)) != null)
{
// This is true both for FormDataElementBase and all derived
// but I want to hide Remove method inside MainGroup class
// However it is displayed again
};
};
}
}
public class BoxGroup : FormDataElementBase
{
}
public class PanelGroup : FormDataElementBase
{
}
public class MainGroup : FormDataElementBase
{
private void Remove()
{
}
}
When user right click, application will display PopupMenu (GenerateGroupPopupMenuItems method). Items of menu will be based on methods who has CandidateApiForMenuItem declared. However, there are derived class (MainGroup) where some methods (f.e: Remove) should not be displayed. What I did, inside MainGroup declared Remove method as private. However, it is displayed again.
Could you pls let me know what I am doing worng here?
Thanks.
First of all, this.GetType().GetMethods() without parameters returns only public instance (i.e. non-static) methods. So MainGroup.Remove won't be returned by this call.
If you make MainGroup.Remove public, this.GetType().GetMethods() will return both methods - for base class and for derived one. Not what you want, I suppose.
If you make FormDataElementBase.Remove virtual and MainGroup.Remove override, GetMethods will return only one Remove method (with DeclaringType==typeof(MainGroup)) - this is better.
And finally, I'd suggest to introduce one more attribute, say, CandidateApiIgnore. If we mark an overridden method with this attribute and modify in the following way GenerateGroupPopupMenuItems method, the stuff should work:
[AttributeUsage(AttributeTargets.Method)]
public sealed class CandidateApiIgnore : Attribute
{
public CandidateApiIgnore() { }
}
public class FormDataElementBase
{
///...
[CandidateApiForMenuItem("Remove")]
public virtual void Remove()
{
///...
}
public void GenerateGroupPopupMenuItems()
{
foreach (MethodInfo methodInfo in this.GetType().GetMethods())
{
if (methodInfo.GetCustomAttribute(typeof(CandidateApiForMenuItem)) != null &&
methodInfo.GetCustomAttribute(typeof(CandidateApiIgnore)) == null)
{
// If a method is overridden and marked with
// CandidateApiIgnore attribute in a derived
// class, it won't be processed here.
};
};
}
public class MainGroup : FormDataElementBase
{
[CandidateApiIgnore]
public override void Remove()
{
throw new NotSupportedException();
}
}
Is there a way to force the override of a virtual method if another method is overriden?
public class BaseClass
{
protected virtual void A()
{
// a default action called first
}
protected virtual void B()
{
// a default action called second that,
// if A was overriden, makes no sense
}
}
EDIT
Thanks a lot for the Answers. It's very interresting to see how this could be achieved, but for my explicit case it's not critically important.
Also, i forgot to mention how those Methods would be used: (in BaseClass)
pulbic bool EditEntity(Guid id)
{
A();
// Some code that edits Entites
B();
}
No, you cannot. But this makes me think how could you achieve the same concept?
The best idea I came up with was declaring an interface which had the package of methods to override.
public interface IMyOverridablePackage
{
void A_Override();
void B_Override();
}
Then give the base class a protected method where the child class can explicitly override the set of methods.
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
So then here's two classes, one which does and one which does not override the set of methods:
public class NotOverriding : MyBaseClass
{
}
public sealed class Overriding : MyBaseClass, IMyOverridablePackage
{
public Overriding()
{
SetOverride(this);
}
void IMyOverridablePackage.A_Override()
{
Console.WriteLine("Overriding.A_Override");
}
void IMyOverridablePackage.B_Override()
{
Console.WriteLine("Overriding.B_Override");
}
}
And the implementation of the base class:
public abstract class MyBaseClass
{
private IMyOverridablePackage _overridablePackage;
public void A()
{
_overridablePackage.A_Override();
}
public void B()
{
_overridablePackage.B_Override();
}
private class MyDefaultPackage : IMyOverridablePackage
{
private readonly MyBaseClass _myBaseClass;
internal MyDefaultPackage(MyBaseClass myBaseClass)
{
_myBaseClass = myBaseClass;
}
void IMyOverridablePackage.A_Override()
{
_myBaseClass.A_Impl();
}
void IMyOverridablePackage.B_Override()
{
_myBaseClass.B_Impl();
}
}
protected MyBaseClass()
{
_overridablePackage = new MyDefaultPackage(this);
}
private void A_Impl()
{
Console.WriteLine("MyBaseClass.A_Impl");
}
private void B_Impl()
{
Console.WriteLine("MyBaseClass.B_Impl");
}
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
}
This does achieve the goal, but of course you have to ask 'how much to I want it?' Is it worth the extra code?
Here's a working dotnetfiddle: https://dotnetfiddle.net/xmPn20
Maybe you cannot force it via compiler errors, but you could write a test which asserts that the methods are in sync via some attributes. It would also be visible that there is some dependency.
A crude example would be something like this:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class VersionAttribute : Attribute
{
public VersionAttribute(string version)
{
Version = version;
}
public string Version { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DependentAttribute : Attribute
{
public string DependentOnMethod { get; set; }
public string DependentOnVersion { get; set; }
}
[Dependent(DependentOnMethod = "OtherMethod", DependentOnVersion = "1")]
public static void FirstMethod()
{
}
[Version("1")]
public static void OtherMethod()
{
}
And the test that asserts the version numbers:
[Test]
public void TestVersions()
{
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
foreach (var method in type.GetMethods())
{
foreach (var customAttribute in method.GetCustomAttributes())
{
var dependent = customAttribute as DependentAttribute;
if (dependent != null)
{
var methodInfo = type.GetMethod(dependent.DependentOnMethod);
Assert.That(methodInfo, Is.Not.Null, "Dependent method not found");
VersionAttribute version = methodInfo.GetCustomAttributes().OfType<VersionAttribute>().FirstOrDefault();
Assert.That(version, Is.Not.Null, "No version attribute on dependent method");
Assert.That(dependent.DependentOnVersion, Is.EqualTo(version.Version));
}
}
}
}
}
thus, if you update one of your methods you would need to update the version number of either the Version attribute or the Dependent attribute. Hopefully better than nothing.
You may change your design :
public abstract class BaseClass
{
protected abstract void A();
}
public class BaseClassEx
{
protected sealed override void A()
{
// action Calling B
}
protected virtual void B()
{
// a default action called second
}
}
In the case of Equals (actually both Equals overloads, concrete type and object) and GetHashCode, Resharper includes a rule that shows a warning in its IntelliSense whenever you forget to implement one of these.
You could enforce it in your code with a runtime check in the constructor of the base class:
public class Base
{
public Base()
{
var baseA = typeof (Base).GetRuntimeMethod("MethodA", new Type[0]);
var baseB = typeof (Base).GetRuntimeMethod("MethodB", new Type[0]);
var derivedA = GetType().GetRuntimeMethod("MethodA", new Type[0]);
var derivedB = GetType().GetRuntimeMethod("MethodB", new Type[0]);
if (baseA.DeclaringType == derivedA.DeclaringType ^
baseB.DeclaringType == derivedB.DeclaringType)
throw new InvalidOperationException("You must override MethodA and MethodB together.");
}
public virtual string MethodA() { return "Hello"; }
public virtual int MethodB() { return 123; }
}
To clarify: I have two forms that use the same method in my Controller, and I was wondering how to use the same lines of code rather than copying and pasting the method and using a different parameter for each method.
Eg. What I have now:
public static void PopulateOriginCombo(CableID_QueryView QView)
{
if (QView.cmbAreaCode.Text != "")
{
//Code...
}
}
public static void PopulateOriginCombo(CableID_CreateView CView)
{
if (CView.cmbAreaCode.Text != "")
{
//Code...
}
}
Can I combine the parameters of each form into one somehow?
Since you want to avoid inheritance, create an interface:
interface IHasOriginCombo
{
ComboBox cmbAreaCode { get; }
}
then, in your class declarations, add the interface:
class CableID_QueryView : Form, IHasOriginCombo { //...
class CableID_CreateView : Form, IHasOriginCombo { //...
then:
public static void PopulateOriginCombo(IHasOriginCombo view)
{
if (view.cmbAreaCode.Text != "")
{
//Code...
}
}
You don't need to use inheritance to do this. Create another class which contains your methods and returns list of objects, then use it on different forms.
public class Origin
{
public string originName { get; set; }
public static List<Origin> PopulateOriginCombo(CableID_QueryView QView)
{
if (QView.cmbAreaCode.Text != "")
{
//Code...
}
}
public static List<Origin> PopulateOriginCombo(CableID_CreateView CView)
{
if (CView.cmbAreaCode.Text != "")
{
//Code...
}
}
}
Then in your form, call it like this:
combo1.DataSource = Origin.PopulateOriginCombo(test);
combo1.DisplayMember = "originName";
Using objects is hard at first, but eventually you will find it easier to manipulate.
how about create class that has this method than you can call this method :
public static string PopulateOriginCombo(CableID_CreateView CView)
{
if(CView != null)
{
if (CView.cmbAreaCode.Text != "")
{
return CView.Text ;
}
}
return string.Empty;
}
than just create object from that class and call this method and pass the CView to it like that :
SomeClass classObject = new SomeClass();
string value = classObject.PopulateOriginCombo(this.CView);
Methods specific for customers:
I try to refactore a code, where are a lot of logic for specifi customer:
public void SendDocumentsToCustomer(List<Case> cases)
{
foreach(var case in cases)
{
if(case.CustomerId==123)
{
if(case.Type==1 || case.Type==2)
{
SendDocumentsToCustomer123(case)
}
else if(case.CustomerId==456)
{
if(case.Type==1 || case.Type==3)
{
SendDocumentsToCustomer456(case);
}
}
else if(case.CustomerId==768)
{
if(case.Type==2)
{
SendDocumentsToCustomer456(case);
}
else
{
SendDocumentsToCustomer(case);
}
}
}
The list of specific customer will grow, and the conditions will be modified as well. I will have a generic solution, but maybe code like this with method DoItForClient123 is not a bad solution and I should leave it like that and goint this way introduce methods like CanDocumentsBeSendToClient123 and so on?
I will be very gratefull for some input
To separate logic for each specific customer I would use such code:
abstract class DocumentSender //Base class for all document sending components
{
public abstract bool CanSend(Case #case); // Check if sender can send the document
public abstract void SendDocument(Case #case); // Send the document
}
class DefaultDocumentSender : DocumentSender
{
public override bool CanSend(Case #case)
{
return true; //Can process all requests
}
public override void SendDocument(Case #case)
{
// Do something
}
}
class Customer123DocumentSender : DocumentSender
{
public override bool CanSend(Case #case)
{
return #case.CustomerId == 123; //Specific case
}
public override void SendDocument(Case #case)
{
if(#case.Type==1 || #case.Type==2)
{
// Do something different
}
}
}
//Separate class for getting the correct sender
class CaseSenderFactory
{
readonly List<DocumentSender> _senders = new List<DocumentSender>();
public DocumentSenderFactory()
{
//Initialize the list of senders from the most specific.
_senders.Add(new Customer123DocumentSender());
// Add more specific cases here
_senders.Add(new DefaultDocumentSender()); //Last item should be the default sender
}
public DocumentSender GetDocumentSender(Case #case)
{
//At least one sender needs to satisfy the condition
return _senders.First(x => x.CanSend(#case));
}
}
You then can use the senders like this:
var factory = new DocumentSenderFactory();
foreach(var #case in cases)
{
var sender = factory.GetDocumentSender(#case);
sender.SendDocument(#case);
}
I think it would be a good ideea to make something like this:
The ideea is if the code is really specific to some of the Customers then you could make a class for them. If the code for specific customers somehow related but combined in a diferent way then you should take a loot at DecoratorPattern(mabye it helps)
class Customer
{
public abstract SendDocumentsTo(Customer c);
}
class SpecificCustomerA
{
public overwrite SendDocumentsTo(Customer c)
{
if (c is SpecificCustomerB)
{
//Logic here
}
}
}
class SpecificCustomerB { ... }