第二次作业-熟悉使用工具
GIT地址 | |
GIT用户名 | luomei1547 |
学号后五位 | 62201 |
博客地址 | |
作业链接 | https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/homework/2793 |
1. 准备工作
1.1 安装 VS 2017
本次作业所需的vs 2017 已经在过去的c#课程中配置完成了,在以往的配置中未出现问题,最终环境如下图所示:
1.2 注册Github
在使用Microsoft Edge进入https://github.com/join并注册GitHub账号的时候,一直被提示无法核实验证码,如下图所示:
登录提示链接以后,提示需要使用支持的浏览器,并列举了支持的浏览器类别,如下图所示:
其中Microsoft Edge是支持的,但使用Microsoft Edge有时也会出现无法显示身份验证的模块的问题,所以就去下载了Firefox ,
在Firefox中一步一步成功完成了注册和登录。
1.3 安装git
进入https://git-scm.com/download/win后浏览器界面显示开始下载,如下图所示:
但实际上仿佛没有任何的活动,然后点击“click here to download manually”,于是跳出了下载界面。
点击“保存文件”后,任务正式开始下载
这里需要说明一点,在Firefox中下载的速度是很慢的,但一般都可以成功下载,需要有点耐心,或者找其他下载源。
运行安装包后,按照步骤就可以安装成功了。
2. 代码设计
2.1 题目背景
阿超家里的孩子上小学一年级了,这个暑假老师给家长们布置了一个作业:家长每天要给孩子出一些合理的,但要有些难度的四则运算题目,并且家长要对孩子的作业打分记录。作为程序员的阿超心想,既然每天都需要出题,那何不做一个可以自动生成小学四则运算题目与解决题目的命令行 “软件”呢。他把老师的话翻译一下,就形成了这个软件的需求:程序接收一个命令行参数 n,然后随机产生 n 道加减乘除(分别使用符号+-*/来表示)练习题,每个数字在 0和 100 之间,运算符在 2 个 到 3 个之间。由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中不得出现非整数,比如不能出现 3÷5+2=2.6 这样的算式。练习题生成好后,将生成的 n 道练习题及其对应的正确答案输出到一个文件 subject.txt 中。当程序接收的参数为4时,以下为一个输出文件示例。
13+17-1=29
11*15-5=160
3+10+4-16=1
15÷5+3-2=4
2.2 代码设计具体思路
根据题目,可以把这次任务简单的分成三个部分 :
① 生成规定操作符数量的四则运算表达式,这一步比较简单,因为操作数永远比操作符多一个,所以可以利用循环,随机生成一个字符串,这里需要注意随机数的种子选取问题,一般默认下选用的是机器时钟时间,相比较计算机的运算速度来说,容易产生误差,所以可以自定义种子值,以提高随机数的随机性。
1 //提高随机数的随机性,给定种子值iSeed 2 byte[] buffer = Guid.NewGuid().ToByteArray(); 3 int iSeed = BitConverter.ToInt32(buffer, 0); 4 Random rand = new Random(iSeed);
② 计算生成的四则运算表达式,并判断其结果是否符合要求,其中运算过程不能出现小数几乎可以等价于结果不能为小数,因为在操作符只有2、3个的四则运算中,只有除法会产生小数,从而导致结果产生小数,当操作符个数为2时,可以等价,但是当操作符个数为3时,在形如 1/2+1/2=1、1/3-1/3=0 ……中会出现过程中有小数,但是结果为整数的情况,这是因为,两个小数相加减,可以出现整数结果,所以在这里,可以直接判断生成的式子中若出现两个“/”时,直接舍去这一结果,可以避免判断每一部分是否为整数。计算一个四则运算表达式的字符串,可以使用DataTable.Compute,DataTable.Compute可以正确计算3/2以及2/3,
所以不需要考虑内部乘除结果,但实际操作下来,发现直接对DataTable.Compute测试是成功的,但在整个程序运行的结果来看,还是出现了保存了存在非整数的算式,所以在源代码中还是判断了除号的位置,导致运算量增加了不少,并且由于是舍弃一部分可能性,导致随机生成的式子中出现除号的概率比较低。
③ 将符合要求的结果存入文件中,在存入第一个式子时,开始计数,不符合条件的不存入,不计数,直至计数值等于接收到的参数N即可结束程序。在这个问题中,我还增加了一个每次运行时都会先清空文件中上一次的内容,因为我觉得,单纯的在同一个txt文本中不断的增加随机四则运算就会出现大量已经出过的题还保留在文件中,如涉及到避免重复出题,则可以不清空文件,把这个文件当做总数据进行查重,但题目中未提出该点要求,所以在这里选择了清空文件已有的内容,仅存放每次运行后的结果。
1 //保存 2 static public string Save(string expression,string expression_double) 3 { 4 try 5 { 6 if (expression != null && expression_double!= null) 7 { 8 DataTable dt = new DataTable(); 9 double answer = Convert.ToDouble(dt.Compute(expression_double, "false")); 10 11 if (Convert.ToDouble(Convert.ToInt32(answer)) == answer && answer >= 0) 12 { 13 File.AppendAllText(@".\subject.txt", expression + "=" + (int)answer + "\r\n"); 14 return answer.ToString(); 15 } 16 return null; 17 } 18 else return null; 19 } 20 catch 21 { 22 return null; 23 } 24 }
至此,整个程序就可以完成了
3. 克隆项目以及提交代码
3.1 使用github将项目克隆到自己的github仓库中
进入https://github.com/Jupi4ter/AchaoCalculator后,点击右上角的“Fork”,即可完成。
3.2 使用git将项目保存到本地
在进行上一步的“Fork”操作后,界面会自动转到登录用户自己的仓库中,点击“Clone or download”,就可以看到一个克隆地址。
打开Git Bash,并输入git clone <url>
运行结束后,在打开Git Bash的目录下就会出现克隆到本地的项目。如直接在桌面创建Git Bash,则克隆的项目就存在桌面上。
3.3 代码的提交
在完成源代码的编写以及测试后,可以查看一下仓库状态,并提交。
然后点击自己仓库界面的“New Pull Request”,然后点击Create pull request 即可成功提交。
可在Jupi4ter的仓库中查看自己提交的状态。
4. 测试过程及效能工具的体验
4.1 单元测试
在进行单元测试时,在函数名上右击会有一个创建单元测试的选项,可以快速创建单元测试。在这里需要注意,Program需要设置成public才能成功创建。也可以右键单击解决方案,添加一个新建项目,在类型里选择:单元测试。
但是由函数自动生成的代码中,会出现Assert.Fail(); 然后进行测试时,显示,三个测试均未通过。
注释掉三个Assert.Fail();测试就可以通过了
上网查了一下Assert.Fail();的作用:在不检查任何条件的情况下使断言失败,
根据源代码以及题目要求,设计了如下的测试用例
1 using Microsoft.VisualStudio.TestTools.UnitTesting; 2 using calculator; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace calculator.Tests 10 { 11 [TestClass()] 12 public class ProgramTests 13 { 14 [TestMethod()] 15 public void AddTest() 16 { 17 //判断计数是否准确 18 Assert.AreEqual(Program.Add(5), 5); 19 } 20 21 [TestMethod()] 22 public void AutoTest() 23 { 24 //判断是否能成功生成一个运算表达式的字符串 25 Assert.AreEqual(Program.Auto(2, 3, 0, 100), true); 26 } 27 28 [TestMethod()] 29 public void SaveTest() 30 { 31 //判断结果为负数是否舍去 32 Assert.IsNull(Program.Save("3-2-3")); 33 //判断结果为小数是否舍去 34 Assert.IsNull(Program.Save("3/5+2")); 35 //判断出现除零错误是否舍去 36 Assert.IsNull(Program.Save("1/0-1")); 37 //判断符合要求并保存的算式的结果是否正确 38 Assert.AreEqual(Program.Save("2+8/2"), (6).ToString()); 39 } 40 } 41 }
利用单元测试的确使我们的测试可以实行自动化,但是在编写具体的测试代码的时候,是要花很大的功夫去思考的,如何测试,要测试哪些数据,没有返回值的函数如何找出有测试价值的地方。
接下来,是对断点的熟悉,断点可以很方便的帮助我们观察函数中某一局部变量的变化情况,而且可以根据特定的输入走特定的路径,可以帮助我们检测程序的路径是否有效,还可以帮助我们判断某一变量在特定语句结束后,是否能够达到预期值等等很多问题。
4.2 回归测试
回归测试的重点就是防止程序“退化”,为了体验回归测试,修改了源程序代码的一个小地方,将不出现负数的判断条件删除后, Assert.IsNull(Program.Save("3-2-3"));这个测试应该是通不过的,所以让我们一起看一下结果吧
结果跟预想的一样,因为测试用例是根据题目要求和运算规范设计过的,所以在修改源程序后,在上一次测试中可以通过的测试用例出现了错误,这就是发生了“退化”,回归测试的重点在于避免程序越写越错,保证程序是在正确的基础上“进化”的,这一点是很重要的,在没有接触到回归测试的时候,每次写代码,改着改着,就发现前面用过的成功的输入再次使用时发生了错误,只好再继续改代码,很容易越改越错。
4.3 效能工具
根据作业提示,成功查看了代码的效能分析
并创建了详细的报告,如下图所示,可以明确代码哪部分的cpu占用高,就可以有针对性的进行代码的优化。
5. 感想
英语是得学好,很多网站都是英文界面,虽然现在大多数可以自动翻译成中文,但对官方的英文网站的内容翻译偏差太大了,所以我认为专业英文的学习还是非常重要的。在接触了单元测试和回归测试后,对测试用例的重要性,以及测试自动化的重要性有了更直观的感受。了解到git和github对版本的控制也是非常有利于日常工作的记录和保存的。总之,在这一次作业中,了解到了相当多的新知识,有很多因为时间关系,只能浅显的了解了一下,深入的了解还需要后续投入更过的时间, 我相信,好的工具的使用是会提高我们的工作效率的。
同时,因为此次作业有较为详细的步骤指导,所以很少发生问题,只是对于git的工作模式不太了解,所以整个作业花了大部分时间去查资料,去搞清楚git的工作机制,第一次接触这种工具,万事开头难,在看了很多人的介绍以后,对git有了大概的了解,对它所起的作用也有了自己的理解与认识。
最后是通过这一次课,感受到了很久没敲代码的坏处,很多常用的语句语法都需要翻书确认一下,虽然前段时间在敲微信小程序的代码,但是已经很久没敲过c#的代码了,我觉得,每天都敲一点代码,对自己的能力会有不错的提升,起码在以后的具体工作中可以减少查资料,翻书的时间,把更多的时间用在优化代码上。