昨天已经把 DemoCalculate 中的 Calculate 方法检验参数的部分抽离出来,写成一只只的个别方法,这样的好处是可以为这些方法单独写测试,若而後要修改这些方法时,彼此之间是互不影响,所以找问题相较紧耦合的第一版,第二版的写法更符合 SOLID 原则。不过若要再进一步探讨的话,还可以持续精进程序码,所以今天就来探讨如何更近一步精进。
那一样,我们先来撰写更新一版的测试码,如下:
public class DemoCalculateTests_Ver3
{
[Test]
public void NormalCaseTest()
{
// 与 Day-28 一样
}
[Test]
public void FailCaseTest_MathIsNotNumeric()
{
// 与 Day-28 一样
}
[Test]
public void FailCaseTest_MathIsInZeroToTen()
{
// 与 Day-28 一样
}
[Test]
public void AvgCaseTest_Country()
{
// Arrange
string txtID = "Day-29";
string txtName = "SunShineYen";
string txtMath = "8";
string txtLiteral = "4";
string isCountry = "true";
DemoCalculate_Ver2 testObject
= new DemoCalculate_Ver2(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.Calculate();
// Assert
Assert.AreEqual(result, "Day-29 SunShineYen 6.5");
}
[Test]
public void AvgCaseTest_City()
{
// Arrange
string txtID = "Day-29";
string txtName = "SunShineYen";
string txtMath = "8";
string txtLiteral = "4";
string isCountry = "false";
DemoCalculate_Ver2 testObject
= new DemoCalculate_Ver2(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.Calculate();
// Assert
Assert.AreEqual(result, "Day-29 SunShineYen 6");
}
}
这当中我们新增了检验平均值是否符合预期,基於平均的回传是一串字串,所以我们也撰写相对应的字串做验证。
这当中是可以修改方法以利扩充,因 Calculate 是公开的方法,因此不论是检验参数,或验证平均都需要经过 Calculate 方法,但倘若全部公开,则一些极机密的方法就会被公开,所以可撰写针对检验参数与验证平均分别写独立的方法,这样不但可以做测试,也可以再扩充其他方法时使用,如下:
public class DemoCalculate_Ver3
{
private string txtID;
private string txtName;
private string txtMath;
private string txtLiteral;
private string isCountry;
public DemoCalculate_Ver3(string inTxtID, string inTxtName,
string inTxtMath, string inTxtLiteral, string inIsCountry)
{
txtID = inTxtID;
txtName = inTxtName;
txtMath = inTxtMath;
txtLiteral = inTxtLiteral;
isCountry = inIsCountry;
}
public string Calculate()
{
if (CheckInitPara() != "没错误")
{
return CheckInitPara();
}
return StudentAvg();
}
// 检验参数
public string CheckInitPara()
{
if (MathInputValid() != "没错误")
{
return MathInputValid();
}
if (LiteralInputValid() != "没错误")
{
return LiteralInputValid();
}
return "没错误";
}
private string MathInputValid()
{
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()
{
double result;
if (!double.TryParse(txtLiteral, out result))
{
return "发生错误!文学数值应该是个 numeric!";
}
if (((Convert.ToDouble(txtLiteral) > 10)) || (Convert.ToDouble(txtLiteral) < 0))
{
return "发生错误!文学数值应该介於 0 ~ 10 之间!";
}
return "没错误";
}
// 计算数值
public string StudentAvg()
{
double douMath = Convert.ToDouble(txtMath);
double douLite = Convert.ToDouble(txtLiteral);
if (Convert.ToBoolean(isCountry))
{
return txtID + " " + txtName + " "
+ CountryAvg(douMath, douLite).ToString();
}
else
{
return txtID + " " + txtName + " " + CityAvg(douMath, douLite).ToString();
}
}
private double CountryAvg(double dbMath, double dbLiteral)
{
return (dbMath + dbLiteral + 1) / 2;
}
private double CityAvg(double dbMath, double dbLiteral)
{
return (dbMath + dbLiteral) / 2;
}
}
因此,我们的测试码撰写就可以变成如下:
public class DemoCalculateTests_Ver3
{
[Test]
public void NormalCaseTest()
{
// Arrange
string txtID = "Day-29";
string txtName = "SunShineYen";
string txtMath = "8";
string txtLiteral = "4";
string isCountry = "true";
DemoCalculate_Ver3 testObject
= new DemoCalculate_Ver3(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.Calculate();
// Assert
Assert.AreEqual(result, "Day-29 SunShineYen 6.5");
}
[Test]
public void FailCaseTest_MathIsNotNumeric()
{
// Arrange
string txtID = "Day-29";
string txtName = "SunShineYen";
string txtMath = "Haha";
string txtLiteral = "4";
string isCountry = "not Important";
DemoCalculate_Ver3 testObject
= new DemoCalculate_Ver3(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.CheckInitPara();
// Assert
Assert.AreEqual(result, "发生错误!数学数值应该是个 numeric!");
}
[Test]
public void FailCaseTest_MathIsInZeroToTen()
{
// Arrange
string txtID = "Day-29";
string txtName = "SunShineYen";
string txtMath = "12";
string txtLiteral = "4";
string isCountry = "not Important";
DemoCalculate_Ver3 testObject
= new DemoCalculate_Ver3(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.CheckInitPara();
// Assert
Assert.AreEqual(result, "发生错误!数学数值应该介於 0 ~ 10 之间!");
}
[Test]
public void AvgCaseTest_Country()
{
// Arrange
string txtID = "Day-29";
string txtName = "SunShineYen";
string txtMath = "8";
string txtLiteral = "4";
string isCountry = "true";
DemoCalculate_Ver3 testObject
= new DemoCalculate_Ver3(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.StudentAvg();
// Assert
Assert.AreEqual(result, "Day-29 SunShineYen 6.5");
}
[Test]
public void AvgCaseTest_City()
{
// Arrange
string txtID = "Day-29";
string txtName = "SunShineYen";
string txtMath = "8";
string txtLiteral = "4";
string isCountry = "false";
DemoCalculate_Ver3 testObject
= new DemoCalculate_Ver3(txtID, txtName, txtMath, txtLiteral, isCountry);
// Act
string result = testObject.StudentAvg();
// Assert
Assert.AreEqual(result, "Day-29 SunShineYen 6");
}
}
重构的手法百百种,在此示范的也不是说可适用於每种情况,只要在重构前与後的程序码都能符合测试码就算是合格的重构。不过经由重构的程序码,通常其扩充性较佳,较能做後续的维护。
>>: Day14 用React Component去规划整个画面
在很多情况下,我们需要通过程序去处理一些文本,文本都是以字符串表示的,所以我们今天来看一看,使用 C...
前言 昨天的文章提到 Ingress 其实也可以用来做负载平衡,只是要利用其他种方式来实现,所以接下...
JavaScript 语言 (JavaScript Programming Language) Ja...
承上篇,谈到 v-for,就要说说它的最佳良伴——key。 v-for 必须绑定代表唯一值的 key...
目的 当系统需要提供「复原功能」、「取消复原功能」、「回复到上一个步骤」等需要将这些资料暂时存放在记...