I'm trying out Cake (C# Make). So far all the examples and documentation have the script file declaring all of its code inside delegates, like this:
Task("Clean")
.Does(() =>
{
// Delete a file.
DeleteFile("./file.txt");
// Clean a directory.
CleanDirectory("./temp");
});
However, one of the reasons I'm interested in using Cake is the possibility of writing my build scripts in a similar way to how I write code, as the scripts use a C#-based DSL. Included in this possibility is the ability to separate code that I use into methods (or functions / subroutines, whatever terminology is appropriate) so I can separate concerns and reuse code. For example, I may want to run the same set of steps for a multiple SKUs.
While I realize that I could create my own separate DLL with Script Aliases, I would like to avoid having to recompile a separate project every time I want to change these bits of shared code when working on the build script. Is there a way to define, inline with the normal build.cake file, methods that can still run the Cake aliases (e.g., DeleteFile) and can themselves be called from my Cake tasks?
Cake is C#, so you can create classes, methods, just like in regular C#
I.e. declare a class in a cake file
public class MyClass
{
public void MyMethod()
{
}
public static void MyStaticMethod()
{
}
}
and then use it a script like
var myClass = new MyClass();
// Call instance method
myClass.MyMethod();
//Call static method
MyClass.MyStaticMethod();
The Cake DSL is based on Roslyn scripting so there are some differences, code is essentially already in a type so you can declare a method without a class for reuse
public void MyMethod()
{
}
and then it can be called like a global methods
MyMethod();
A few gotchas, doing class will change scoping so you won't have access to aliases / context and global methods. You can get around this by i.e. passing ICakeContext as a parameter to class
public class MyClass
{
ICakeContext Context { get; }
public MyClass(ICakeContext context)
{
Context = context;
}
public void MyMethod()
{
Context.Information("Hello");
}
}
then used like this
// pass reference to Cake context
var myClass = new MyClass(Context);
// Call instance method which uses an Cake alias.
myClass.MyMethod();
You can have extension methods, but these can't be in a class, example:
public static void MyMethod(this ICakeContext context, string message)
{
context.Information(message);
}
Context.MyMethod("Hello");
Related
I am very new to C# and nunit. Pls bear with me if this is basic and has been already been asked here.
We have a global setup,defined by [SetupFixture] class,which is expected to be run only once. The private variables are defined in it's [setup]. We wish to use the same variables in all our testfixtures,hence inheriting the testbase class in all our testfixtures.
But, while executing Testcase1, i observe that globalSetup() is called more than once. Can anyone point me the issue? sample code is as below.
namespace CTB
{
[SetupFixture]
public class Testbase
{
private byte val1;
private byte val2;
[setup]
public void globalSetup
{
val1 = 5;
val2 = 10;
}
[Teardown]
public void globalTeardown
{
//
}
}
}
namespace CTB.Testcase
{
public class TestCase : Testbase
{
[Setup]
public void Setup()
{
}
[Teardown]
public void Teardown()
{
}
[Test]
public void Testcase1()
{
byte val3 = val1 + val2; // Expect 15
}
}
}
I'm assuming that the answer to my comment is "No" and that you are using a current version of NUnit 3. Please correct me if I'm wrong. :-)
You have made the class TestBase serve two functions:
It's the base class for your TestFixture and therefore it's a TestFixture itself.
It's marked as a SetUpFixture so it also serves that function - a completely different function, by the way.
To be clear, you should never do this. It's a sort of "trick" that almost seems designed to confuse NUnit - not your intention of course. Your test fixtures should have no inheritance relationship with any SetUpFixture. Use different classes for the test fixture base and the setup fixture.
With that out of the way, here is the longer story of what is happening...
Before your tests even execute, the SetUpFixture is first "run" - in quotes because it actually does nothing. That's because it doesn't contain any methods marked with [OneTimeSetUp] or '[OneTimeTearDown]`.
NOTE: As an alternate explanation, if you are using a pretty old version of NUnit, the [SetUp] and [TearDown] methods are actually called at this point. Nnit V2 used those attributes with different meanings when encountered in a SetUpFixture versus a TestFixture.
Next your tests execute. Before each test, the inherited [SetUp] and [TearDown] methods are run. Of course, these are actually the same methods as in step 1. NUnit has been tricked into doing this!
Here is some general guidance for the future...
If you want multiple fixtures to use the same data, a base class is useful. Any public or protected fields or properties will be shared by the inheriting fixtures.
If you want to do some common setup or teardown for a group of unrelated test fixtures, use a SetUpFixture. Note that the only way to pass data from a SetUpFixture to the test fixtures is through static fields or properties. Generally, you use a SetUpFixture to set up the environment in which the test is run, not to provide data.
Never use the same class for both purposes.
I have a common interface that describes access to the output stream like this:
interface IOutput {
function writeInteger(aValue:Int):Void;
}
And I have an abstract implementation of this interface based on standard haxe.io.BytesOutput class:
abstract COutput(BytesOutput) from BytesOutput {
public inline function new(aData:BytesOutput) {
this = aData;
}
public inline function writeInteger(aValue:Int):Void {
this.writeInt32(aValue);
}
}
Though this abstract is truly implementing interface described above there's no direct reference to interface and when I'm trying to use it like this:
class Main {
public static function out(aOutput:IOutput) {
aOutput.writeInteger(0);
}
public static function main() {
var output:COutput = new BytesOutput();
out(output); // type error
}
}
Compiler throws an error: COutput should be IOutput. I can solve this problem only through using common class that wraps BytesOutput and implements IOutput.
My question is how to show the Haxe compiler that the abstract implements the interface.
Abstracts can't implement interfaces because they're a compile-time feature and don't exist at runtime. This conflicts with interfaces, they do exist at runtime and dynamic runtime checks like Std.is(something, IOutput) have to work.
Haxe also has a mechanism called structural subtyping that can be used as an alternative to interfaces. With this approach, there's no need for an explicit implements declaration, it's good enough if something unifies with a structure:
typedef IOutput = {
function writeInteger(aValue:Int):Void;
}
Unfortunately, abstracts aren't compatible with structural subtyping either due to the way they're implemented.
Have you considered using static extensions instead? At least for your simple example, that seems like the perfect solution for making a writeInteger() method available for any haxe.io.Output:
import haxe.io.Output;
import haxe.io.BytesOutput;
using Main.OutputExtensions;
class Main {
static function main() {
var output = new BytesOutput();
output.writeInteger(0);
}
}
class OutputExtensions {
public static function writeInteger(output:Output, value:Int):Void {
output.writeInt32(value);
}
}
You could even combine this with structural subtyping so writeInteger() becomes available on anything that has a writeInt32() method (try.haxe link):
typedef Int32Writable = {
function writeInt32(value:Int):Void;
}
As #Gama11 states, abstracts cannot implement interfaces. In Haxe, for type to implement an interface, it must be able to be compiled to something class-like that can be called using the interface’s methods without any magic happening. That is, to use a type as its interface, there needs to be a “real” class implementing that type. Abstracts in Haxe compile down to their base type—the abstract itself is entirely invisible after compilation happens. Thus, at runtime, there is no instance of a class with the methods defined in your abstract which implement the interface.
However, you can make your abstract appear to implement an interface by defining an implicit conversion to the interface you are trying to implement. For your example, the following might work:
interface IOutput {
function writeInteger(aValue:Int):Void;
}
abstract COutput(BytesOutput) from BytesOutput {
public inline function new(aData:BytesOutput) {
this = aData;
}
#:to()
public inline function toIOutput():IOutput {
return new COutputWrapper((cast this : COutput));
}
public inline function writeInteger(aValue:Int):Void {
this.writeInt32(aValue);
}
}
class COutputWrapper implements IOutput {
var cOutput(default, null):COutput;
public function new(cOutput) {
this.cOutput = cOutput;
}
public function writeInteger(aValue:Int) {
cOutput.writeInteger(aValue);
}
}
class Main {
public static function out(aOutput:IOutput) {
aOutput.writeInteger(0);
}
public static function main() {
var output:COutput = new BytesOutput();
out(output);
out(output);
}
}
Run on try.haxe.org
Note that, each time an implicit conversion happens, a new instance of the wrapper will be constructed. This may have performance implications. If you only access your value through its interface, consider setting the type of your variable to the interface rather than the abstract.
This is similar to “boxing” a primitive/value type in C#. In C#, value types, defined using the struct keyword, are allowed to implement interfaces. Like an abstract in Haxe, a value type in C# is compiled (by the JITter) into untyped code which simply directly accesses and manipulates the value for certain operations. However, C# allows structs to implement interfaces. The C# compiler will translate any attempt to implicitly cast a struct to an implemented interface into the construction of a wrapper class which stores a copy of the value and implements the interface—similar to our manually authored wrapper class (this wrapper class is actually generated by the runtime as part of JITing and is performed by the IL box instruction. See M() in this example). It is conceivable that Haxe could add a feature to automatically generate such a wrapper class for you like C# does for struct types, but that is not currently a feature. You may, however, do it yourself, as exemplified above.
I try to extend my MyDSLProposalProvider from an external Eclipse RCP Project. I created an extension point schema which requires a class property which extends my ProposalProvider. In the new project I extend the class an overrode some methods justs to give me some output so I can see that the external method is called. But this is currently not happening. Is there anything I have to consider?
Currently the hirachy looks like:
MyDSLProposalProvider extends AbstractMyDSLProposalProvider
ExternalProposalProvider extends MyDSLProposalProvider
I rewrote a Method generated in the AbstractMyDSLProposalProvider but when its triggered the predefined Method in the AbstractMyDSLProposalProvider is called and not my new implementation.
public class ExternalMyDSLProposalPovider extends MyDSLProposalProvider
{
#Override
public void completeComponent_Name(EObject model, Assignment
assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
System.err.println("extern");
if(model instanceof Component)
{
createProposal("foo", "foo", context, acceptor);
}
super.completeComponent_Name(model, assignment, context, acceptor);
}
}
This is the class in the external Eclipse Project.
Thanks for the help.
When you declare an extension point using a schema that you have defined Eclipse puts that declaration in the extension point registry. That is all that is does, you must then write code to make uses of those declarations.
You read the extension point registry using something like:
IExtensionRegistry extRegistry = Platform.getExtensionRegistry();
IExtensionPoint extPoint = extRegistry.getExtensionPoint("your extension point id");
IConfigurationElement [] elements = extPoint.getConfigurationElements();
elements is now an array of the declarations in the various plugins using the extension point.
IConfigurationElement has various methods to get the values of the attributes of the declaration.
If you have defined a class in one of the attributes you can create an instance of the class using:
IConfigurationElement element = .... a config element
Object obj = element.createExecutableExtension("attribute name");
In your case the result should be your ExternalMyDSLProposalPovider.
You will then need to hook this object up with whatever is doing to proposals.
How do I create a template that each time when I create a class that extends MyClass, it will automatically add 3 functions.
EDIT:
In other words I am trying to implement Abstract functionality in AS3. Assume that MyClass have both private and protected methods.
I see the only way to write own code template and call it every time you need, in Flash Builder: window->preference->flash builder->editors->code template->action script->new and give the name to the template, for instance myclass.
You can use existed templates as an example for template syntax.
Template code for MyClass child class with three methods:
import my.package.MyClass
/**
* #author ${user}
*/
public class ${enclosing_type} extends MyClass
{
public function ${enclosing_type}()
{
}
override public function publicMethod():void
{
}
override protected function protectedMethod():void
{
}
override private function privateMethod():void
{
}
${cursor}
}
Usage:
Create new "action script file" or "new class",
remove all file content
type myclass and choose from auto-complete options template myclass
If you are actually extending MyClass, all of MyClass's functions are already available to your descendants. You can also override either of them with old header and desired new body, and still be able to call older versions of those functions via super qualifier. So, you add those functions to MyClass and let them be.
Another way is to make an interface - it's a set of declarations without any function bodies, which you have to implement in any class that wants this interface in its content. A short introduction to interfaces. Then your MyClass will be an interface, with 3 function declarations in it, and whichever class will be declared as implements MyClass will have to provide bodies for these functions.
Check other keywords on that page, including extends and implements.
Hope this helps.
EDIT: There are no abstract classes in AS3, however you can emulate abstract functions in a normal class via exception throwing:
protected function abstractFunction(...params):void {
throw new Error("Abstract!");
}
I would like to be able to run tests on my fake repository (that uses a list)
and my real repository (that uses a database) to make sure that both my mocked up version works as expected and my actual production repository works as expected. I thought the easiest way would be to use TestCase
private readonly StandardKernel _kernel = new StandardKernel();
private readonly IPersonRepository fakePersonRepository;
private readonly IPersonRepository realPersonRepository;
[Inject]
public PersonRepositoryTests()
{
realPersonRepository = _kernel.Get<IPersonRepository>();
_kernel = new StandardKernel(new TestModule());
fakePersonRepository = _kernel.Get<IPersonRepository>();
}
[TestCase(fakePersonRepository)]
[TestCase(realPersonRepository)]
public void CheckRepositoryIsEmptyOnStart(IPersonRepository personRepository)
{
if (personRepository == null)
{
throw new NullReferenceException("Person Repostory never Injected : is Null");
}
var records = personRepository.GetAllPeople();
Assert.AreEqual(0, records.Count());
}
but it asks for a constant expression.
Attributes are a compile-time decoration for an attribute, so anything that you put in a TestCase attribute has to be a constant that the compiler can resolve.
You can try something like this (untested):
[TestCase(typeof(FakePersonRespository))]
[TestCase(typeof(PersonRespository))]
public void CheckRepositoryIsEmptyOnStart(Type personRepoType)
{
// do some reflection based Activator.CreateInstance() stuff here
// to instantiate the incoming type
}
However, this gets a bit ugly because I imagine that your two different implementation might have different constructor arguments. Plus, you really don't want all that dynamic type instantiation code cluttering the test.
A possible solution might be something like this:
[TestCase("FakePersonRepository")]
[TestCase("TestPersonRepository")]
public void CheckRepositoryIsEmptyOnStart(string repoType)
{
// Write a helper class that accepts a string and returns a properly
// instantiated repo instance.
var repo = PersonRepoTestFactory.Create(repoType);
// your test here
}
Bottom line is, the test case attribute has to take a constant expression. But you can achieve the desired result by shoving the instantiation code into a factory.
You might look at the TestCaseSource attribute, though that may fail with the same error. Otherwise, you may have to settle for two separate tests, which both call a third method to handle all of the common test logic.