Refactoring legacy code with the regular old incremental approach,
If dealing with large messy procedurial code extract logic you intend on changing into some
reasonably named method or function and if possible add some test cases that verify your
new method. make whatever god awful hack you have to and if possible paramatize the
change if it is something commonly tweaked like margin width or title so it will be a little
more straight forward to update the next time.
Branching By Abstraction
Open Closed Principle and a Common Business Logic/Persistence Layer
To some extent you might be able to get away with separating out your
presentation, business and persistence layer and writing a new app that
is fully backwards compatible with the legacy solution, or at a minimum
can still handle data inputted by legacy solution. I would probably not
recommend this approach but sometimes it is a reasonable compromise
of time/schedule/resources/required new functionality.
If you are striving for full backwards compatibility you should be saving
everything to the same persistence layers. If you just want forward compatibility
into the new tool then use a new database and new tables or extension tables
to track data not in legacy system.
e.g. if you need to start tracking employers emergency contact and some other fields
don’t modify the existing employee table
(we have no idea what assumptions the legacy data makes about that table) add an extension
table employee_ext id, employee_id, emergency_contact_id, etc_id.
Was getting annoyed today with MsTest’s support for inline datasources for test cases. Started work on a little work around hack to simply generate and inject the xml files behind the scenes.
I ideally I will be able to inject enough logic into mstest that I can get rid of that intermediary as well.
For now I have
[DataProviderMethodName("DataProviderExample")]
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\TestMethod1.xml", "scenario", DataAccessMethod.Sequential)]
public void UseRawDataProviderEntries()
{
System.Diagnostics.Trace.WriteLine("somestring = " + TestContext.DataRow["somestring"].ToString());
System.Diagnostics.Trace.WriteLine("Gotcha = " + TestContext.DataRow["Gotcha"].ToString());
Assert.IsTrue((bool)RawDataProviderContext["Gotcha"]);
}
And I want to atleast get to
[DataProviderMethodName("DataProviderExample")]
[TestMethod]
public void UseRawDataProviderEntries()
{
int t = 3243;
System.Diagnostics.Trace.WriteLine("somestring = " + TestContext.DataRow["somestring"].ToString());
System.Diagnostics.Trace.WriteLine("Gotcha = " + TestContext.DataRow["Gotcha"].ToString());
Assert.IsTrue((bool)RawDataProviderContext["Gotcha"]);
}
although . . .
[TestMethod]
[DataProviderMethodName("DataProviderExample")]
public void UseRawDataProviderEntries(bool Gotcha, string somestring)
{
int t = 3243;
System.Diagnostics.Trace.WriteLine("somestring = " + somestring);
System.Diagnostics.Trace.WriteLine("Gotcha = " + Gotcha.ToString());
Assert.IsTrue(Gotcha);
}
//===============
// And
//===============
[TestMethod]
[InlineDataSet]
[DataSet("gotcha column","some string column")]
[DataSet("just used reflection "," to read attributes and plug them in order of appearance into testmethod")]
public void UseRawDataProviderEntries(string gotcha, string somestring)
{
int t = 3243;
System.Diagnostics.Trace.WriteLine("somestring = " + somestring);
System.Diagnostics.Trace.WriteLine("gotcha = " + gotcha);
Assert.IsTrue(Gotcha == "true");
}
would be swell.
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
using System.IO;
using System.Runtime.Serialization;
using System.Xml.Serialization;
namespace TestProject1
{
[System.AttributeUsage(System.AttributeTargets.Method)]
public class DataProviderMethodName : System.Attribute
{
private string name;
public double version;
public string Name
{
get
{
return name;
}
}
public DataProviderMethodName(string name)
{
this.name = name;
version = 1.0;
}
}
[TestClass]
public abstract class HackThePlanet
{
//todo encapsulate further
protected static Dictionary>> _dataprovidercache = new Dictionary>>();
protected Dictionary RawDataProviderContext
{
get
{
if (TestContext.DataRow["meta_provider"] != null)
{
return _dataprovidercache[TestContext.DataRow["meta_provider"] + "_" + TestContext.DataRow["meta_providerhash"]][int.Parse(TestContext.DataRow["meta_index"].ToString())];
}
else
{
return new Dictionary();
}
}
}
private TestContext testContextInstance;
///
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
}
[TestClass]
public class UnitTest1 : HackThePlanet
{
static public List> DataProviderExample()
{
return new List>()
{
new Dictionary { {"Gotcha", false} , {"somestring","value2"} },
new Dictionary { {"Gotcha", true} , {"somestring","value3"} },
new Dictionary { {"Gotcha", false} , {"somestring","value2"} },
};
}
static public List> DataProviderExample2()
{
return new List>()
{
new Dictionary { {"Gotcha", false} , {"agag","value2"} },
new Dictionary { {"Gotcha", true} , {"agag","value3"} },
new Dictionary { {"Gotcha", false} , {"agag","value2"} },
};
}
[ClassInitialize()]
public static void SetupClass(TestContext testContext)
{
var d = new DataSourceAttribute("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\XMLFile1.xml", "row", DataAccessMethod.Sequential);
var de = new DeploymentItemAttribute("TestProject1\\XMLFile1.xml");
MethodInfo[] methodInfos = typeof(UnitTest1).GetMethods(BindingFlags.Public | BindingFlags.Instance);
foreach(var m in methodInfos)
{
var t = m.Attributes;
var a = m.GetCustomAttributes(false);
var UseDataProviderMethodList = (from dpm in a
where dpm.GetType() == typeof(DataProviderMethodName)
select dpm);
if (UseDataProviderMethodList.Count() > 0)
{
// Grab DataSourceAttribute
var DataSourceAttributeList = (from dsa in a
where dsa.GetType() == typeof(DataSourceAttribute)
select dsa);
if (DataSourceAttributeList.Count() > 0)
{
var DataProviderMethodName = ((DataProviderMethodName)UseDataProviderMethodList.First()).Name;
var DataProviderMethod = typeof(UnitTest1).GetMethod(DataProviderMethodName);
var dataset = (List>)DataProviderMethod.Invoke(null, new object[0]);
//todo add some hash logic here if we want to allow dataprovider to return non determanistic data.
var hash = DateTime.Now.GetHashCode();
_dataprovidercache[DataProviderMethodName + "_" + hash] = dataset;
var DataSource = (DataSourceAttribute)DataSourceAttributeList.First();
//todo better support for different location preferences.
var requestedFile = DataSource.ConnectionString.Replace("|DataDirectory|\\", "\\");
//todo use xml tools for htis
string output = "";
output += "\n";
output += "\n";
int index = 0;
foreach (Dictionary scenario in dataset)
{
output += "\n";
// record keeping
output += "" + (index++) + " ";
output += "" + DataProviderMethodName + " ";
output += "" + hash + " ";
foreach (KeyValuePair kv in scenario)
{
output += " <" + kv.Key.Replace("\"", "\\\"") + ">" + kv.Value.ToString().Replace("\"", "\\\"") + "" + kv.Key.Replace("\"", "\\\"") + ">\n";
}
output += " \n";
}
output += " \n";
System.IO.File.WriteAllText(testContext.DeploymentDirectory + requestedFile, output);
}
}
}
}
[TestMethod]
public void TestMethod1()
{
this.ToString();
bool k = true;
Assert.IsTrue(k);
}
//@todo Implement some way of preventing overwrites to the same DataSource.XML file ( preferably alter what is stored in the runner for xml name and
// just replace with testcase name to insure uniqueness.
[DataProviderMethodName("DataProviderExample")]
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\TestMethod1.xml", "scenario", DataAccessMethod.Sequential)]
public void UseRawDataProviderEntries()
{
int t = 3243;
System.Diagnostics.Trace.WriteLine("somestring = " + TestContext.DataRow["somestring"].ToString());
System.Diagnostics.Trace.WriteLine("Gotcha = " + TestContext.DataRow["Gotcha"].ToString());
Assert.IsTrue((bool)RawDataProviderContext["Gotcha"]);
}
[DataProviderMethodName("DataProviderExample2")]
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\TestMethod2.xml", "scenario", DataAccessMethod.Sequential)]
public void UseRegularTestContext()
{
int t = 3243;
System.Diagnostics.Trace.WriteLine("agag = " + TestContext.DataRow["agag"].ToString());
System.Diagnostics.Trace.WriteLine("Gotcha = " + TestContext.DataRow["Gotcha"].ToString());
Assert.IsTrue(TestContext.DataRow["agag"].ToString() == "value3");
}
}
}
. . .
Courtesy of the long list of things you probably shouldn’t do but will anyway heres how one goes about implementing mutex locking between multiple powershell scripts.
<# 1. Instantiate Mutex Object using new-object syntax 2. Use the same "DesiredMutexName" across scripts. Or move mutex logic into a shared script included by each script desiring access to these mutexes. (. Path\ScriptWithMutexLocks.ps1) #> $mutex = new-object -TypeName System.Threading.Mutex -ArgumentList $false, "YourDesiredMutexName"; # 3. Lock Access to critical sections in each script $result = $mutex.WaitOne(); <# Critical Section #> #4 Release $mutex.ReleaseMutex(); <# Script Specific / Non viotile section #>
. . . Enjoy
I’ve been working on a port of JBehave/Cucumber for PHPUnit. So far things are looking good and I am getting very close to pushing my source code up to the google project page.
Essentially I hsve setup a test suite class that uses some simple regex logic to map test step functions to the plain text sentences stored in my test text file. I’ve got a long way to go in terms of polish and finish but the initial work looks pretty good so far.
Andrescue has a couple of just genius approaches to generic meta programming his book “Modern C++ Generic Programming and Design Patterns Applied.” I really recommend checking it out.

Categories
Tag Cloud
Blog RSS
Comments RSS
Last 50 Posts
Back
Void « Default
Life
Earth
Wind
Water
Fire
Light 