VSoft Technologies Blogs

rss

VSoft Technologies Blogs - posts about our products and software development.


Today we updated Delphi Mocks to enable the Mocking of multiple interfaces. This is useful when the interface you wish to Mock is cast to another interface during testing. For example you could have the following system you wish to test.

type
  {$M+}
  IVisitor = interface;

  IElement = interface
    ['{A2F4744E-7ED3-4DE3-B1E4-5D6C256ACBF0}']
    procedure Accept(const AVisitor : IVisitor);
  end;

  IVisitor = interface
    ['{0D150F9C-909A-413E-B29E-4B869C6BC309}']
    procedure Visit(const AElement : IElement);
  end;

  IProject = interface
    ['{807AF964-E937-4A8A-A3D2-34074EF66EE8}']
    procedure Save;
    function IsDirty : boolean;
  end;

  TProject = class(TInterfacedObject, IProject, IElement)
  protected
    function IsDirty : boolean;
    procedure Accept(const AVisitor : IVisitor);
  public
    procedure Save;
  end;

  TProjectSaveCheck = class(TInterfacedObject, IVisitor)
  public
    procedure Visit(const AElement : IElement);
  end;
  {$M-}

implementation

  { TProjectSaveCheck }

  procedure TProjectSaveCheck.Visit(const AElement: IElement);
  var
    project : IProject;
  begin
    if not Supports(AElement, IProject, project) then
      raise Exception.Create('Element passed to Visit was not an IProject.');

    if project.IsDirty then
      project.Save;
  end;

The trouble previously was that when testing TProjectSaveCheck a TMock<IElement> would be required, as well as a TMock<IProject>. This is brought about by the Visit procedure requiring the IElement its passed to be an IProject for the work its going to perform.

This is now very simple with the Implement<I> method available off TMock<T>. For example to test that Save is called when IsDirty returns true, the following test could be written;

procedure TExample_InterfaceImplementTests.Implement_Multiple_Interfaces;
var
  visitorSUT : IVisitor;
  mockElement : TMock<IElement>;
begin
  //Test that when we visit a project, and its dirty, we save.

  //CREATE - The visitor system under test.
  visitorSUT := TProjectSaveCheck.Create;

  //CREATE - Element mock we require.
  mockElement := TMock<IElement>.Create;

  //SETUP - Add the IProject interface as an implementation for the mock
  mockElement.Implement<IProject>;

  //SETUP - Mock project will show as dirty and will expect to be saved.
  mockElement.Setup<IProject>.WillReturn(true).When.IsDirty;
  mockElement.Setup<IProject>.Expect.Once.When.Save;

  //TEST - Visit the mock element to see if our test works.
  visitorSUT.Visit(mockElement);

  //VERIFY - Make sure that save was indeed called.
  mockElement.VerifyAll;
end;

The Mock mockElement "implements" two interfaces IElement, and IProject. IElement is done via the constructor, and IProject is added through the Implement<I> call. The Implement<I> call adds another sub proxy to the mock object. This sub proxy then allows all the mocking functionality to be performed with the IProject interface.

To access the Setup, and Expects behaviour there are overloaded generic calls on TMock. These return the correct proxy to interact with, and generic type ISetup<I> and IExpect<I>. This is seen in the call to mockElement.Setup<IProject>. This returns a ISetup<IProject> which allows definition of what should occur when IProject is used from the Mock.

This feature is really useful when there is a great deal of casting of interfaces done in the system you wish to test. It can save having to mock base classes directly where multiple interfaces are implemented.

The way this works under the hood is fairly straight forward. TVirtualInterfaces are used when an interface is required to be mocked. This allows the capturing of method calls, and the creation of the interface instance when its required.

The Implement<I> functionality simply extends this so that when a TProxyVirtualInterface (inherited from TVirtualInterface) has QueryInterface called it also looks to its owning Proxy. If any other Proxies implement the requested interface its that TProxyVirtualInterface which is returned.

In essence this allows us to fake the Mock implementing multiple interfaces, when in fact there are a list of TVirtualInterface's all implementing a single interface.


GitHub's Status API allows you to update the status of a commit, or pull request. Continua CI 1.0 has an Action which allows you to do this during a Stage, but it is somewhat cumbersome to use, because you typically need three actions to update the status to pending at the start of the stage, and then success or failure at the end. 

Build Event Handlers

Continua CI 1.5 adds a new feature to Configurations - Build Event Handlers.  These are tasks that run on the Server (unlike Stages & Actions which run on the Agent). In Continua CI 1.5 there are handlers for Octopus Deploy, Tagging Repository Changesets and Updating GitHub Status (which is the focus of this post).

So lets take a look at the Update GitHub Status event handler. Build Event Handlers are on the (new) Events page of the Configuration Wizard - click on [Create] to add a new handler

Adding a new Event Handler

Give the Event Handler a Name and select the "Update GitHub Status" type. The handler specific tabs will then show up

Set the credentials and repositories to update

Note, use either your GitHub Username and Password, or an Access Token (you can create one in your GithHub user profile - applications page). Specify the name(s) of the repositories you want to update. Note that these must match the names of Continua CI repositories associated with the build. 

Specify when to run the status updates

You can specify the Start and End Stages, which control when the status is updated to Pending and then Success or Failure. 

Specify the status messages

You can customise the status messages - the default ones will insert the project & configuration names along with the build version. Note that GitHub Status messages have a 140 char limit (must have some ex twitter staff, why else would the limit be so short??).

Misc options

If you don't care about the results of the status updates, you can turn off the 'Wait for Results" option and your build will take a few seconds less. 

Ok, so what happens when you run a build. In this example, I told Continua CI to build a pull request branch, and when the build starts, I see this on the Pull request page :

Build Pending

When the build completes successfully I see this :

Build Success

This is an immensely useful feature, I have this configured on my open source projects on GitHub, and usually by the time I get to look at the pull request, Continua CI has already built it and updated the status. If the build failed, well then I know not to bother merging. 

One of the most asked for features in Continua CI 1.0 was the ability to control which stages run, ie the ability to skip stages dynamically, based on what happened earlier in the build, and to be able to control whether the build should continue on to the next stage or wait for user intervention.  In Continua CI 1.5, we made this possible with Skip and Promote Conditions.

Skip Conditions

Skip Conditions allow you to controll whether a Stage is skipped or run based on expressions. All the expressions must evaluate to true for the stage to run (if there are no expressions then the stage will not be skipped). 

Skip Conditions

In the above example, we have a Stage called Obfuscate, and we want it to be skipped if you turn off obfuscation (by setting a variable) or if we are not deploying a build (again, controlled by a variable). You can also disable a stage completely so it is always skipped.

Promote Conditions

In Continua CI 1.0, you can chose if the next Stage is automatically run, or the builds stops and requires a manual promotion to continue to the next Stage. In Continua CI 1.5, Promote Conditions allow you control whether to automatically promote or not, based on expressions.  All the expressions must evaluate to true for the build to continue to the next stage (if there are no expressions then the build will stop with a status of waiting for promotion). 

Skip Conditions

In the above example, our build will continue on to the next Stage if the Deploy variable is set to true. 

Continua CI 1.5 is currently in Beta - you can get it here :
http://www.finalbuilder.com/downloads/continuaci/continuaci-beta-version-history 

So you've got your Continua CI server set up to automatically build, run unit tests and produce reports for your awesome new web application. Now you're ready to try out your project in its natural environment and then eventually release it to the wild for well-deserved public applause.

Up until now, your options were either to use a Copy action to push the files up to test server and a PowerShell action to set up web services, or preferably run a FinalBuilder script utilising the plethora of actions available for transferring files and interacting with web servers.

As of version 1.5, Continua CI can also work together with Octopus Deploy server to provide an end-to-end continuous delivery mechanism. Using the new build event handlers feature, Continua CI builds can now be set up to create Octopus Deploy releases and initiate deployment to test and production environments, at key points in the build process.

This post will walk through the steps required to push a .Net web application built in Continua to Octopus Deploy and trigger a deployment process to effortlessly get your application running on your test and production servers.

Preparing your solution


Octopus Deploy requires that you provide your applications as NuGet packages. You can create and push the package to the Octopus Deploy server using Nuget Pack and Push actions, or create and push an OctoPack from MSBuild or VisualStudio build runner actions.

Lets go with the recommended OctoPack option. First prepare your Visual Studio solution - use the NuGet package manager to install the OctoPack package into the projects you want to deploy. This will include web application projects, console application projects and Windows service projects but not class libraries and unit test projects.



You can now optionally add a .nuspec file to the root folder of your project to describe the contents of your package. If you don't provide a .nuspec file, OctoPack will automatically create one based on your project settings.



Setting up the deployment process


Next head over to your Octopus server and set up a deployment project. This should include a “Deploy a NuGet package” process step as below.



We will set this to retrieve the application package from the built-in NuGet feed. Note that the NuGet package id should match the id element in your .nuspec file - this will default to the name of your assembly.

We added a few more steps:



And some variables:



Setting up the build process


You can now get back to Continua and set up a configuration for building your project. Once you have entered the configuration details and linked up the repository containing your project, move on over to the Stages page:



For this simple example you'll need two actions: a NuGet Restore action to ensure that the OctoPack package is available for the build and an MSBuild action to build and push the application to your Octopus Deploy server.
Just enter the path to your solution for the NuGet Restore action (the other fields can be left as is) and complete the main tab of the MSBuild action as required for your project.



You then need to enter some additional properties to tell MSBuild to run OctoPack and tell it where to send your package.



Set the RunOctoPack property to true and the OctoPackPublishPackageToHttp property to the URL for the NuGet feed on the Octopus Deploy server e.g. http://octopusserver/nuget/packages.

You will also need to provide an OctoPackPublishAPIKey property – you can generate an API key on your profile page on the Octopus Deploy server.

Optionally, you can  use the OctoPackPackageVersion to specify up the package version. Here we use Continua expressions to set this based on the build version. If you leave this out then OctoPack will get this value from the AssemblyVersion property in your AssemblyInfo.cs file.

Once the actions are set up and saved, run a build and check that your package gets uploaded to the Octopus Deploy server. Then create a release for your deployment project and test that it deploys ok. Now we are ready to look into how to run this process automatically from Continua CI.

Build event handler


On the Continua CI configuration wizard after Stages, we have a new area titled Events. Here you can add Build Event Handlers for tagging repository changesets, updating the GitHub status and interacting with Octopus Deploy.

Create a new build event handler, give it a name and select the Octopus Deploy as the Type.




You can now provide general project details under the Octopus Deploy tab.



The Octopus Deploy URL should end with '/api' e.g. http://octopusserver/api. Enter the API key generated under your Octopus Deploy profile and the name of your deployment project.
  
You can then choose one or more actions to run. The available options are Create, Deploy and Promote and are used to create a new deployment release, deploy a release to an environment and promote a release from one environment to another. As you select each action, new tabs open so you can provide further details and hook the action to a build event.

Creating a release


Before you can deploy an application you need to create a Octopus Deploy release




When creating a release you can specify the Release Version or leave this blank to automatically create a number based on the highest package version. You must provide either a Default Package Version or Step Package Versions for each step which requires one e.g.




Flip over to the Create Options tab to tell Continua when to create the release.




There are six Build Events available to choose from. Some allow you to select a Stage and some allow you to select a successful or failed Build Status

  • On Before Stage Start
  • On Sending Stage To Agent
  • On Stage Completed
  • On Build Pending Promotion
  • On After Build Continued
  • On Build Completed

Generally we want to create the release at the start of the build before the first stage starts.

Deploying to an environment


Now on to the crux of this whole process - deploying your application. We generally deploy to a Test environment first and then, once we are happy with the outcome, promote to a User Acceptance environment or directly to Production. Continua CI allows you to deploy a release previously created by a Create action in the same build event handler, the highest release version in the project or a specific release version. It's up to you to ensure that the release version exists before the deploy action is run. An environment can consist of multiple machines - you can specify which machines you want to deploy to. If no machines are specified then the release will be deployed to all machines in the environment.





When selecting the Build Event for deployment, ensure that it is triggerred after the package has been built and pushed to the Octopus Deploy server. Here we have set this to be run once the Build stage has completed successfully.



Promoting a release


You can promote the latest release from one environment to another. Ideally this would be linked to the promotion of a stage e.g. a testing stage, so that the application can be promoted from a test environment to production environment.



We have set our test stage to require manual promotion;




and set our promote action to run when a build is continued after waiting for promotion.



Variables


You can also pass variables from Continua CI to your deployment, these will be sent to the Octopus Deploy server before each action is run, updating the variables for the deployment project. We have used expressions is this example to send the build versions number and branch name. These variables can then be used to update project files with details for display or configure services differently depending on the source of the project.



Running the configuration


Once your build event handler dialog has been completed and saved, its time to start running the configuration. As the build processes Continua CI will display status information mirroring the process running on Octopus Deploy.



You can also see full details of the deployment process in the build log.



And all going well you will now see a successful deployment on your Octopus Deploy server!








With the upcoming 1.5 release of ContinuaCI  we have made a number of enhancements to the dashboards, we think you'll love them!  Here is a peek at what's coming soon.

The New List View

all-projects-listview

Improvements:
  • - Stage indicator blocks provide quick drill-down into the build log.
  • - Improved viability and responsiveness of build actions buttons.
  • - Build action buttons moved to the left for easier access.
  • - Viability enhancements around projects.
  • - Improved Responsiveness and performance tweeks.

List View: With Builds Completed

all-projects-listview-completed-builds

List View: With Builds Running

all-projects-listview-completed-multibuilds

The New Details View

details-view

Improvements:
  • - Build and Queue times now have graphs!
  • - Build status card on the left hand side displays the status of the build as it progresses.
  • - Build action buttons are more obvious and responsive.
  • - Stage indicator blocks (present on the build status cards) provide quick drill-down into the build log.
  • - Improved Responsiveness and performance tweeks.

Details View: with Builds Queued

details-view-queued

Details View: with Builds Executing

details-view-building

Details View: with Builds Finished

details-view-finished

Stay tuned for more exciting details regarding the version 1.5 release!