昨天有提到我们在 Console 执行应用程序时,可以依序输入 ID、名字、数学数值、文学数值与 isCountry 布林值,而後会执行计算平均值的方法,并给出相对应的平均值又或是提供错误讯息;然而,该方法里面牵涉的商业逻辑,各参数检验是否为合理彼此并没有相对的关系,但以被绑在同一只方法,这样对於系统的维护困难(假设随着功能的扩大,里面有 20-30 个参数要检验),对於测试码的撰写也是极其复杂的。因此,我们今天先重构第一版的商业逻辑与测试码。
昨天 Day-27 流程图有提到,我们在重构完程序码後需要跑测试码来验证重构後的程序码是符合预期的结果,那在 Day 19 Roy Osherove 曾提到重构是「在不改变程序码功能的前提下,修改程序码的动作。」;因此,我们要先撰写第一版的测试,以验证目前的行为在测试下的结果,如下:
public class DemoCalculateTests_Ver1
{
[Test]
public void NormalCaseTest()
{
// Arrange
string txtID = "Day-28";
string txtName = "SunShineYen";
string txtMath = "8";
string txtLiteral = "4";
string isCountry = "true";
DemoCalculate testObject
= new DemoCalculate(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.Calculate();
// Assert
Assert.AreEqual(result, "Day-28 SunShineYen 6.5");
}
[Test]
public void FailCaseTest_MathIsNotNumeric()
{
// Arrange
string txtID = "Day-28";
string txtName = "SunShineYen";
string txtMath = "Haha";
string txtLiteral = "4";
string isCountry = "true";
DemoCalculate testObject
= new DemoCalculate(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.Calculate();
// Assert
Assert.AreEqual(result, "发生错误!数学数值应该是个 numeric!");
}
[Test]
public void FailCaseTest_MathIsInZeroToTen()
{
// Arrange
string txtID = "Day-28";
string txtName = "SunShineYen";
string txtMath = "12";
string txtLiteral = "4";
string isCountry = "true";
DemoCalculate testObject
= new DemoCalculate(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.Calculate();
// Assert
Assert.AreEqual(result, "发生错误!数学数值应该介於 0 ~ 10 之间!");
}
// ...
}
执行结果:
上面测试码为示意,测试的情境还可以撰写数个测试方法如文学数值是否为 Numeric、文学数值是否介於 0-10 等。而接下来要探讨的是撰写重构程序码,而大致上要做的项目有几点,如下:
因此,程序码如下:
namespace HelloRefactor
{
class Program
{
// ...
public class DemoCalculate_Ver2
{
private string txtID;
private string txtName;
private string txtMath;
private string txtLiteral;
private string isCountry;
public DemoCalculate_Ver2(string inTxtID, string inTxtName, string inTxtMath, string inTxtLiteral, string inIsCountry)
{
txtID = inTxtID;
txtName = inTxtName;
txtMath = inTxtMath;
txtLiteral = inTxtLiteral;
isCountry = inIsCountry;
}
public string Calculate()
{
string MathInputValidResult = MathInputValid(txtMath);
string LiteralInputValidResult = LiteralInputValid(txtLiteral);
if (MathInputValidResult != "没错误")
{
return MathInputValidResult;
}
if (LiteralInputValidResult != "没错误")
{
return LiteralInputValidResult;
}
if (Convert.ToBoolean(isCountry))
{
return txtID + " " + txtName + " " + CountryAvg(Convert.ToDouble(txtMath), Convert.ToDouble(txtLiteral)).ToString();
}
else
{
return txtID + " " + txtName + " " + CityAvg(Convert.ToDouble(txtMath), Convert.ToDouble(txtLiteral)).ToString();
}
}
private string MathInputValid(string txtMath)
{
double result;
if (!double.TryParse(txtMath, out result))
{
return "发生错误!数学数值应该是个 numeric!";
}
if (((Convert.ToDouble(txtMath) > 10)) || (Convert.ToDouble(txtMath) < 0))
{
return "发生错误!数学数值应该介於 0 ~ 10 之间!";
}
return "没错误";
}
private string LiteralInputValid(string txtLiteral)
{
double result;
if (!double.TryParse(txtLiteral, out result))
{
return "发生错误!文学数值应该是个 numeric!";
}
if (((Convert.ToDouble(txtLiteral) > 10)) || (Convert.ToDouble(txtLiteral) < 0))
{
return "发生错误!文学数值应该介於 0 ~ 10 之间!";
}
return "没错误";
}
private double CountryAvg(double dbMath, double dbLiteral)
{
return (dbMath + dbLiteral + 1) / 2;
}
private double CityAvg(double dbMath, double dbLiteral)
{
return (dbMath + dbLiteral) / 2;
}
}
}
因此,把一开始所撰写的测试码,里面的 DemoCalculate 改成 DemoCalculate_Ver2,跑出来的测试结果如下:
而这样抽出检验参数的好处是,我们在撰写新的测试方法时,可以单独针对每个参数的检验方式写相对应的测试,若参数多达 20-30 种时,出错也可以找出相对应的问题并修改程序码,明天会在继续探讨如何更精进程序码。
>>: D28 - 如何打包 Apps Script 的程序码?(一) 变成扩充功能似的 UI 按键
我在第二次改版本号的时候,发现了这个问题, 像挥之不去的苍蝇一样…死黏着 就像是上面那个他自己跳出来...
学习进度 资料结构 泛型 通配字元 Android Studio RecyclerView Recy...
AI2的List很像阵列, 这个App记录读取List的方式 1.使用到的元件: Layout -&...
前言 刚学习 React 的时候,一定会碰到一个小问题,就是当我们有个值需要存在在两个元件之间,该怎...
torchvision.transforms transforms可以用来改变样本的多样性,例如:旋...