LinqPad and F# Charting

Import these references Sample script Graph

March 2016 · Smart Tech

User story example

Title Wholesale customers created with ‘on-hold’ account status Card Description Wholesale customers created in D365 CE will initially have their account status placed ‘on hold’ to disallow any credit transactions before they have their account credit checked and approved Story AS A finance manager I WANT new wholesale customers to begin with their account status 'oh hold' SO THAT no credit transactions are processed on their account until their account credit checked,approved and taken off hold. [Any supporting notes/diagrams] ...

October 2015 · Smart Tech

Map .html extension to the .Net razor view engine

1. Add the buildProvider config for razor inside the compilation element 2. Application start –> Registers the html extension with razor 3. Create a Start.cshtml page and ingest the index.html page <compilation debug\="true" targetFramework\="4.6" \> <buildProviders\> <add extension\=".html" type\="System.Web.WebPages.Razor.RazorBuildProvider"/> </buildProviders\> </compilation\> System.Web.Razor.RazorCodeLanguage.Languages.Add("html", new CSharpRazorCodeLanguage()); WebPageHttpHandler.RegisterExtension("html"); @{ Layout \= null; @RenderPage("~/index.html") } <!-- Version + @System.Reflection.Assembly.GetAssembly(typeof (Startup)).GetName().Version.ToString(); \-->

September 2015 · Smart Tech

Value Tests --> Eliminate Toil

Write Value Tests Having drank the TDD cool aid over the years I went deep. BDD with Fitnesse, SpecFlow. Maximum code coverage %. Days fixing up UI tests. Ensuring this calls that – all code was covered. Today here is how I calculate a tests value. Will it help me discover a design? Is the functionality well known? (is this feature being tested to see if its used/needed) Will it stop hard to find bugs in the future? Is its value worth maintaining over time? Will the next person be able to understand and appreciate this test? If YES then write the test! ...

July 2015 · Smart Tech

Cloud Terms

Cloud Terms Firstly some terminology courtesy of Stackoverflow IAAS (Infrastructure As A Service) : The base layer Deals with Virtual Machines, Storage (Hard Disks), Servers, Network, Load Balancers etc PAAS (Platform As A Service) : A layer on top of IAAS Runtimes (like .net/java runtimes), Databases (like MSSql, Oracle), Web Servers (IIS/tomcat etc) SAAS (Software As A Service) : A layer on top on PAAS Applications like email (Gmail, Yahoo mail etc), Social Networking sites (Facebook etc) IAAS AWS Azure Digital Ocean Google Cloud PAAS Azure DotCloud SalesForce OpenShift m-brace AppHarbour Heroku SAAS Azure AppHarbour Heroku SalesForce

June 2015 · Smart Tech

Chocolatey machine setup

https://gist.github.com/chrismckelt/3884f94078a7bd3a773b

June 2015 · Smart Tech

From DotNetBlogEngine to WordPress

So after losing 6 months worth of posts I have now converted this blog to use WordPress. To transfers the posts I wrote a simple linqpad script that uses WordPressSharp After trying Syntax highlighter I instead choose this code formatter. // need nuget WordPressSharp internal class FileStore { public IList<Post> Posts { get; private set; } public void ReadFiles() { const string folderPath = @"C:\temp\posts"; Posts = new List<Post>(); var files = Directory.GetFiles(folderPath); files.ToList().ForEach(ProcessFile); } private void ProcessFile(string filepath) { //Load xml XDocument xdoc = XDocument.Load(filepath); //Run query var posts = from lv1 in xdoc.Descendants("post") select new Post() { Title = lv1.Element("title").Value, Content = lv1.Element("content").Value, PublishDateTime = Convert.ToDateTime(lv1.Element("pubDate").Value), CustomFields = GetDesc(new KeyValuePair<string, string>("Description", lv1.Element("description").Value)) }; posts.ToList().ForEach(Posts.Add); } public CustomField[] GetDesc(params KeyValuePair<string,string>[] fieldsToAdd) { var list = new List<CustomField>(); foreach (var keyValuePair in fieldsToAdd) { list.Add(new CustomField() { Id=Guid.NewGuid().ToString(), Key=keyValuePair.Key, Value = keyValuePair.Value }); } return list.ToArray(); } } private static void Main(string[] args) { var url = "http://www.mckelt.com/blog/"; var cfg = new WordPressSiteConfig { BaseUrl = "/blog/xmlrpc.php", BlogId = 1, Username = "username", Password = "password" }; var fs = new FileStore(); fs.ReadFiles(); foreach (var post1 in fs.Posts.OrderBy(x=>x.PublishDateTime)) { post1.Status = "publish"; using (var client = new WordPressClient(cfg)) { client.NewPost(post1); } } } }

June 2015 · Smart Tech

Scrum to kanban

Scrum to Kanban

March 2015 · Smart Tech

Software Development Best Practice (minimum)

Source Control To track versions and manage an environment from deployment to recovery, source control is essential. Tracking changes, performing peer reviews before merging to the main master branch & the ability to rebuild/recover/revert to a previously known good state ensure quality throughout the process. Example source control : GitHub Continue Integration Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early. ...

July 2014 · Smart Tech

Web API Test to ensure public routes do not change

[TestFixture] public class RouteTestFixture { [Test] public void Routes _should _not _change() { const string good = @ "all existing routes go here (hint run the test first then copy output to here)"; var goodRoutes = good.Split(Convert.ToChar(";")); var notFound = new List < string > (); var ass = Assembly.GetAssembly(typeof (EventStatisticsController)); var sb = new StringBuilder(); foreach(var type in ass.GetTypes()) { try { var members = type.GetMembers(); for (int i = 0; i < members.Length; i++) { if (members[i].IsDefined(typeof (RouteAttribute), false)) { Object[] atts = members[i].GetCustomAttributes(typeof (RouteAttribute), false); for (int j = 0; j < atts.Length; j++) { var routeAttribute = (RouteAttribute) atts[j]; string route = routeAttribute.Template + @ "/" + routeAttribute.Name; Console.WriteLine(route); sb.Append(route + ";"); if (!goodRoutes.Contains(route)) { notFound.Add(route); } } } } } catch (Exception e) { Console.WriteLine(@ "An exception occurred: {0}", e.Message); } } if (notFound.Any()) { Console.WriteLine(@ "-- MISSING ROUTES --"); foreach(var nf in notFound) { Console.WriteLine(nf); } Assert.Fail("Missing Routes: " + notFound.Count); } else { Assert.True(true, "All routes matched"); } Console.WriteLine(@ "------------------------------------------------"); Console.WriteLine(@ "Match the following string for future tests"); Console.WriteLine(sb.ToString()); } }

May 2014 · Smart Tech

Software Playbook

Principles we follow Numero Uno Our primary principle is to work as a team to deliver the best outcomes for the business. Transparency We combine face to face and verbal communcation with individual focus and use tools such as Slack, Trello, and GitHub to communicate openly within a project, within our team, and publicly. Honesty While we are considerate of people’s feelings and opinions, we cannot let those concerns get in the way of getting the right outcome for the business and the success of our work. We’d rather be too honest than too polite. ...

February 2014 · Smart Tech

XUnit Ignore test at runtime (with SpecFlow tag @IgnoreLocally)

Code –> https://github.com/chrismckelt/XUnit.OptionallyIgnore NuGet –> https://www.nuget.org/packages/Xunit.SpecFlow.AssertSkip/ As Xunit has no Assert.Ignore() using the OptionallyIgnoreTestFactAttribute attribute on a method and setting McKeltCustom.SpecflowPlugin.Settings.IgnoreLocally == true will ignore the test at runtime In SpecFlow set this as a plugin and use the tag @IgnoreLocally– before each test scenario is run turn on/off the setting to run this test. Sample usage: namespace Tester { public class Dummy { public Dummy() { McKeltCustom.SpecflowPlugin.Settings.IgnoreLocally = true; } } public class TestFixture : IUseFixture<Dummy> { [OptionallyIgnoreTestFact\] public void DoesThisWork() { Assert.True(false, "This should not be run"); } public void SetFixture(Dummy data) { throw new NotImplementedException(); } } } SpecFlow tag can be on a feature or a scenario ...

October 2013 · Smart Tech

Why Agile?

The software design process Why Waterfall fails •Waterfall projects have 3x the failure rate (29% vs. 9%) and 1/3 the success rate (14% vs. 42%) of Agile projects (Standish Group, CHAOS Report 2012) •Inventor of Waterfall Winston W. Royce described in his academic paper written in 1970 that it was “risky and invites failure” and went on to describe Incremental development. •Recent failed waterfall projects that scrapped •UK Govt. £12 Billion for national program for NHS IT ...

August 2013 · Smart Tech

F# Canopy UI tests -- http://lefthandedgoat.github.io/canopy/

` FSharp Canopy Tests namespace RegressionTests open System open System.Configuration open runner open canopy open configuration open reporters open QuoteHelper module QuoteSiteTests = let runTest = ( start chrome let mainBrowser = browser elementTimeout <- 15.0 compareTimeout <- 15.0 let _testpage = ConfigurationManager.AppSettings.\["AolSiteUrl"] let _username = ConfigurationManager.AppSettings.\["AolChallengerId"] let _password = ConfigurationManager.AppSettings.\["AolPassword"] let _passwordChangeToThis = ConfigurationManager.AppSettings.\["AolPasswordChangeToThis"] let _includePasswordChangeTest = ConfigurationManager.AppSettings.\["IncludePasswordChangeTest"] let _quickSearchText = ConfigurationManager.AppSettings.\["QuickSearchText"] let _quickSearchFindInvestor = ConfigurationManager.AppSettings.\["QuickSearchFindInvestor"] let _path = ConfigurationManager.AppSettings.\["OutputTestResults"] QuoteHelper.deleteFiles _path "" true for file in System.IO.Directory.EnumerateFiles(_path) do let tempPath = System.IO.Path.Combine(_path, file) System.IO.File.Delete(tempPath) context ("Testing :: eQuote - " + _testpage + "/Quote") before (fun _ -> describe "Starting test" url (_testpage + "/Quote") ) ntest "Login" (fun _ -> describe ("Login with " + _username) url _testpage "#userId" << _username "#password" << _password click ".submit" // on (_testpage + "/Secure/Home/") ) ntest "GIP Quote - Fixed Term" (fun _ -> describe "Creating GIP quote – fixed 3 year" js "$('input:radio\[name=NewPolicyType]:first').attr('checked', true);" |> ignore click "#btnContinue1" sleep 5 let setQuote = QuoteHelper.createQuoteTerm "100000" "Monthly" "3" js setQuote |> ignore click "#btnRunQuote" sleep 5 click "#btnSaveQuote" sleep 3 let linkText = read "#yourQuoteId" describe linkText screenshot _path linkText |> ignore ) ntest "GIP quote – life" (fun _ -> describe "Creating GIP quote – life" js "$('input:radio\[name=NewPolicyType]::nth(1)').attr('checked', true);" |> ignore click "#btnContinue1" sleep 5 js " $('input:radio\[name=ProductTerm]::nth(1)').click();" |> ignore sleep 1 let setQuote = QuoteHelper.createQuoteLife "100000" "Monthly" js setQuote |> ignore sleep 1 js "$('#InitialCommissionRate').val('0');" |> ignore click "#btnRunQuote" sleep 5 click "#btnSaveQuote" sleep 3 let linkText = read "#yourQuoteId" describe linkText screenshot _path linkText |> ignore ) ntest "GA Quote - Fixed Term" (fun _ -> describe "Creating Fee for service annuity quote - FIXED" js "$('input:radio\[name=NewPolicyType]:first').attr('checked', true);" |> ignore click "#btnContinue1" sleep 5 let setQuote = QuoteHelper.createQuoteTerm "100000" "Monthly" "3" js setQuote |> ignore sleep 1 js "$('#InitialCommissionRate').val('0.0055');" |> ignore click "#btnRunQuote" sleep 5 click "#btnSaveQuote" sleep 3 let linkText = read "#yourQuoteId" describe linkText screenshot _path linkText |> ignore ) ntest "GA quote – life" (fun _ -> describe "Creating GA quote – life" js "$('input:radio\[name=NewPolicyType]::nth(1)').attr('checked', true);" |> ignore click "#btnContinue1" sleep 5 js " $('input:radio\[name=ProductTerm]::nth(1)').click();" |> ignore sleep 1 let setQuote = QuoteHelper.createQuoteLife "100000" "Yearly" js setQuote |> ignore sleep 1 js "$('#InitialCommissionRate').val('0');" |> ignore click "#btnRunQuote" sleep 5 click "#btnSaveQuote" sleep 3 let linkText = read "#yourQuoteId" describe linkText screenshot _path linkText |> ignore ) ntest "GreenId Test" (fun _ -> describe "GreenId Test" js "$('input:radio\[name=NewPolicyType]::nth(1)').attr('checked', true);" |> ignore click "#btnContinue1" sleep 5 js " $('input:radio\[name=ProductTerm]::nth(1)').click();" |> ignore sleep 1 let setQuote = QuoteHelper.createQuoteLife "100000" "Yearly" js setQuote |> ignore sleep 1 js "$('#InitialCommissionRate').val('0');" |> ignore click "#btnRunQuote" sleep 5 click "#btnSaveQuote" sleep 3 let linkText = read "#yourQuoteId" describe linkText click "#btnApply" sleep 5 js QuoteHelper.greenId |> ignore sleep 1 click "#InvestorDetails_IdentityVerification_CheckId" screenshot _path ("GreenId -" + linkText )|> ignore ) run () quit mainBrowser ) namespace RegressionTests module QuoteHelper = let createQuoteTerm amount paymentFrequency term = ( @" $('#InvestorDetails_Title').val('Mr'); $('#InvestorDetails_GivenNames').val('test'); $('#InvestorDetails_Surname').val('client'); $('#InvestorDetails_DateOfBirth_day').val(1); $('#InvestorDetails_DateOfBirth_month').val(1); $('#InvestorDetails_DateOfBirth_year').val(1937); $('#InvestmentAmount').val(" + amount + "); $('#InvestmentAmount_editor').val('$100,000.00'); $('#PaymentFrequency').val('" + paymentFrequency + "'); $('#Term').val('" + term + "'); $('#InitialCommissionRate').val('0'); $('#Indexation').val('ZeroPercent'); $('#OngoingCommissionRate').val('0.00550'); $('#ResidualCapitalValueRate').val('1.00000'); $('#JointInvestorDetails_Title').val('Mr'); $('#JointInvestorDetails_GivenNames').val('joint test'); $('#JointInvestorDetails_Surname').val('client'); $('#JointInvestorDetails_DateOfBirth_day').val(31); $('#JointInvestorDetails_DateOfBirth_month').val(12); $('#JointInvestorDetails_DateOfBirth_year').val(1956);") let createQuoteLife amount paymentFrequency = ( @" $('#InvestorDetails_Title').val('Mr'); $('#InvestorDetails_GivenNames').val('test'); $('#InvestorDetails_Surname').val('client'); $('#InvestorDetails_DateOfBirth_day').val(1); $('#InvestorDetails_DateOfBirth_month').val(1); $('#InvestorDetails_DateOfBirth_year').val(1937); $('#InvestmentAmount').val(" + amount + "); $('#InvestmentAmount_editor').val('$100,000.00'); $('#PaymentFrequency').val('" + paymentFrequency + "'); $('#InitialCommissionRate').val('0.0055'); $('#Indexation').val('ZeroPercent'); $('#OngoingCommissionRate').val('0.00550'); $('#ResidualCapitalValueRate').val('1.00000'); $('#JointInvestorDetails_Title').val('Mr'); $('#JointInvestorDetails_GivenNames').val('joint test'); $('#JointInvestorDetails_Surname').val('client'); $('#JointInvestorDetails_DateOfBirth_day').val(31); $('#JointInvestorDetails_DateOfBirth_month').val(12); $('#JointInvestorDetails_DateOfBirth_year').val(1956);") let greenId = (@" $('#InvestorDetails_ResidentialAddress_UnitNumber').val('5'); $('#InvestorDetails_ResidentialAddress_StreetNumber').val('48'); $('#InvestorDetails_ResidentialAddress_StreetName').val('Manchester'); $('#InvestorDetails_ResidentialAddress_Suburb').val('Gymea'); $('#InvestorDetails_ResidentialAddress_StreetType').val('RD'); $('#InvestorDetails_ResidentialAddress_State').val('NSW'); $('#InvestorDetails_ResidentialAddress_Postcode').val(2227); ") let rec deleteFiles srcPath pattern includeSubDirs = if not <| System.IO.Directory.Exists(srcPath) then let msg = System.String.Format("Source directory does not exist or could not be found: {0}", srcPath) raise (System.IO.DirectoryNotFoundException(msg)) for file in System.IO.Directory.EnumerateFiles(srcPath, pattern) do let tempPath = System.IO.Path.Combine(srcPath, file) System.IO.File.Delete(tempPath) if includeSubDirs then let srcDir = new System.IO.DirectoryInfo(srcPath) for subdir in srcDir.GetDirectories() do deleteFiles subdir.FullName pattern includeSubDirs `

May 2013 · Smart Tech

Powershell & SVN – Export files to CSV

Function Get-SvnLogData() { ([xml](svn log -v --xml 'http://svn/trunk')).log.logentry | % { $nestedEntry = $_ $_.paths.path | % { $path = $_ $nestedEntry | Select-Object -Property ` Author, ` @{n='Revision'; e={([int]$_.Revision)}}, ` @{n='Date'; e={Get-Date $_.Date }}, ` @{n='Action'; e={$path.action }}, ` @{n='Path'; e={$path.InnerText }}` } } } Get-SvnLogData | where { $_.Date -ge (Get-Date '16-04-2013') } | Select-Object Revision,Date,Path,Author | sort -property ` @{ Expression="Path"; Descending=$false }, ` @{ Expression="Revision"; Descending=$true } | Export-CSV c:\test.csv

April 2013 · Smart Tech

13 Steps to exception presentation design (from http://michellebowden.com.au/)

13 Steps to exception presentation design Pace, Pace, Pace Lead WIIFM (What’s in it for me?) – Reduce Maintain Improve POO (Pacing Out Objectives) Frame - (i.e. Agenda Other Speakers) What (from 4Mat) How (from 4Mat) - Other info “by the way” my pleasure Contact Details Summary (why, what, how) Call to action QA Negative & Positive Closing Statement

March 2013 · Smart Tech

NServiceBus Powershell Install

NServiceBus PowerShell Install $Arguments = '/install /startManually /serviceName:{0} /displayName:{0} NServiceBus.Production /username:{1} /password:{2}' -f 'McKelt.securitytokenservice.nservicebus.messagehandler', 'xxxx@au.McKelt.net', 'PasswordGoesHere' $nServiceBus = Resolve-Path -Path nServiceBus.Host.exe; Write-Host -Object ('Argument string is: {0}' -f $Arguments); Write-Host -Object ('Path to nServiceBus.Host.exe is: {0}' -f $nServiceBus); Start-Process -Wait -NoNewWindow -FilePath $nServiceBus -ArgumentList $Arguments -RedirectStandardOutput tmp.txt;

March 2013 · Smart Tech

Powershell script to delete mail from specific folder

function Remove-MailItem { [CmdletBinding(SupportsShouldProcess=$true)] param ( [parameter(Mandatory=$true)] [string]$mailfolder, [string]$parentfolder ) $ol = new-object -comobject "Outlook.Application"; # Map to the MAPI namespace $mapi = $ol.getnamespace("mapi"); $targetfolder = '' if ($parentfolder.Length -eq 0) { $targetfolder = $mapi.Folders.Item(1).Folders.Item("Inbox").Folders.Item($mailfolder) } else { $targetfolder = $mapi.Folders.Item(1).Folders.Item("Inbox").Folders.Item($parentfolder).Folders.Item($mailfolder) } foreach ($item in $targetfolder.Items) { try { $item.Delete() } catch [Exception]{ Write-Host "Failed to delete item: " + $item.Subject Write-Host $_.Exception.ToString() } } function Clear-DeletedMail { $outlook = New-Object -ComObject Outlook.Application foreach ($folder in $outlook.Session.Folders){ foreach($mailfolder in $folder.Folders ) { if ($mailfolder.Name -eq "Deleted Items" -and $mailfolder.Items.Count -gt 0){ foreach ($item in $mailfolder.Items){$item.Delete()} } } } } } Remove-MailItem -mailfolder "Cafe" Remove-MailItem -mailfolder "COLSupport" Remove-MailItem -mailfolder "Failed Logins" -parentfolder "COLSupport" Remove-MailItem -mailfolder "IISReset" -parentfolder "COLSupport" Remove-MailItem -mailfolder "Not Urgent" -parentfolder "COLSupport" Remove-MailItem -mailfolder "Production" -parentfolder "COLSupport"

October 2012 · Smart Tech

Software quotes

Software Quotes “In God we trust. All others must bring data.”- W. Edwards Deming, Statistician “Web users ultimately want to get at data quickly and easily. They don’t care as much about attractive sites and pretty design.”- Tim Berners-Lee Not everything that can be counted counts, and not everything that counts can be counted. William Bruce Cameron (not Albert Einstein) Without An Opinion, You’re Just Another Person With Data - W. Edwards Deming

September 2012 · Smart Tech

Round house and powershell

Using https://github.com/chucknorris/roundhouse for powershell to get automated database change management Task UpgradeDatabase{ if (($environment -eq 'integration') -or ($environment -eq 'uat')) { # round house variables $rh = "C:\\dev\\Phoenix\\trunk\\Tools\\RoundhousE\\console\\rh.exe" $connectionString = "Data Source=localhost;Database=XXX; User Id=XXXuser; Password=XXX;Connect Timeout=100;" $indexesFolder = "C:\\dev\\Phoenix\\trunk\\Database\\10-Indexes" $schemaChangesFolder = "C:\\dev\\Phoenix\\trunk\\Database\\11-SchemaChanges" ## build server? if (Test-Path "D:\\Code\\") { $rh = "D:\\Code\\Phoenix\\trunk\\Tools\\RoundhousE\\console\\rh.exe" $indexesFolder = "D:\\Code\\Phoenix\\trunk\\Database\\10-Indexes" $schemaChangesFolder = "D:\\Code\\Phoenix\\trunk\\Database\\11-SchemaChanges" if ($environment -eq 'integration') { $connectionString = "Data Source=xxxxx;Database=rrrr\_Integration; User Id=rrrr; Password=rrrr;" } else { $connectionString = "Data Source=xxxx;Database=rrrrr\_UAT; User Id=rrrrr; Password=rrrrr;" } } Write\-Host "Database upgrade started" $s1 = " -c " $s2 = " $connectionString " $s3 = " -ix " $s4 = "$indexesFolder" $s5 = " -u " $s6 = "$schemaChangesFolder" $args = $s1 + " ""$s2" "" + $s3 + " ""$s4" "" + $s5 + " ""$s6""" + " -ni -ct 300" Write\-Host $args Start-Process -FilePath $rh -ArgumentList $args -PassThru Write\-Host "Database upgrade complete" } } The following tables are created ...

June 2012 · Smart Tech