• 第二次作业


    1.项目Github地址

    https://github.com/Vertigor/FourOperation

    2.题目

    (四则运算题目生成程序(基于控制台)){https://edu.cnblogs.com/campus/whu/2017ASE/homework/952}

    3.估计花费时间

    PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
    Planning 计划  10  
    · Estimate · 估计这个任务需要多少时间  10  
    Development 开发  360  
    · Analysis · 需求分析 (包括学习新技术)  30  
    · Design Spec · 生成设计文档  20  
    · Design Review · 设计复审 (和同事审核设计文档)  10  
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范)  10  
    · Design · 具体设计  30  
    · Coding · 具体编码  230  
    · Code Review · 代码复审  20  
    · Test · 测试(自我测试,修改代码,提交修改)  10  
    Reporting 报告  60  
    · Test Report · 测试报告  30  
    · Size Measurement · 计算工作量  10  
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划  20  
    合计    430  

    3.

    4.解题思路

      在拿到题目后,一开始想的是算法的实现,后来感觉算法是一定可以实现的,然而运行在什么样的环境,是至关重要的。本来想选用最近一直在用的JAVA,但是由于我不会JAVA的界面编程,最后还是选择了之前比较熟练的C#。又想到这个项目应该有很好的兼容性,网页似乎就是一个不错的选择。但后来又发现题目要求基于控制台,感觉自己白浪费这么多时间在界面上了。汗。。。最后还是用JAVA吧,电脑上的环境已经搭好了,不用重新搭C#的环境了。

      Java是一门面向对象的语言,所以分析题目中的对象是很重要的。首先,要把界面、功能模块、控制分割开,采用MVC模式设计。其次,用户操作的对象是题目,将题目作为对象生成一个类(Question)。题目中要求可以进行真分数的运算,我的想法是把每个数字都当成是真分数来运算,整数相当于分母为1,所以我又生成一个类(Fractions)。光有对象没有操作不行的,我又声明一个类(Calculate),用来计算真分数的加减乘除。最后,生成一个(Control)类,用来处理与用户交互的图形界面,这样程序的框架就搭好了。

      完成框架后,具体设计还需满足以下需求:

    1. 操作数必须随机生成。
    2. 运算符的种类和顺序必须随机生成。
    3. 可以判断用户输入的对错。
    4. 使用-n参数控制生成题目的个数。
    5. 支持带括号的多元复合运算。
    6. 运算符个数随机生成。

      补充:考虑真分数可以约分成整数,所以Fractions中应该包含changeToInteger()函数,将结果保存成整数。括号的数目和位置也应该随机生成,满足数学约束,并且能够嵌套。

    5.设计实现过程

     总流程图

    子流程图

      Fractions用两个int变量分别表示分子分母,提供静态函数maxCommonDivisor(int,int)和minCommonMultiple(int, int),分别是求最大公约数函数和最小公倍数函数,还包含将可转化为整数的分数转化为整数的函数changeToInteger()。

      Question采用两种数组保存操作数,分别是分数操作数和整数操作数,又创建两个括号数组,分别是左括号和右括号,专门的乘除运算符数组以及用于计算的两个堆栈。包括检查括号约束情况函数checkBracket()、计算函数calculate()、优先级比较函数compare(str: char)等。

      Calculate包含四个静态函数,分别是加减乘除。Control包含main函数,从控制台读取到题目个数,与用户进行交互。

    6.代码说明

    代码说明已存在注释中。

    6.1Question类如下:

      1 package question;
      2 
      3 import java.util.Random;
      4 import java.util.Stack;
      5 
      6 import fraction.Fractions;
      7 import calculate.Calculate;
      8 
      9 public class Question {
     10     private Character[] operators;//操作符数组
     11     private int[] operands;//操作数数组
     12     private Fractions[] operands_fra;//操作数分数数组
     13     private int operators_num;//运算符数目
     14     private Fractions result;//计算结果
     15     private Stack<Character> priStack;// 操作符栈   
     16     private Stack<Fractions> numStack;// 操作数栈
     17     private int[] leftBracket;//左括号
     18     private int[] rightBracket;//右括号
     19     private int bracketNum;//括号数量
     20     private String expression;//表达式字符串
     21     public Question(int operators_num){
     22         if(operators_num<1||operators_num>10){
     23             System.out.println("Error:operators number error!");
     24             return;
     25         }
     26         this.operators_num = operators_num;
     27         this.operands = new int[operators_num+1];
     28         this.operators = new Character[operators_num];
     29         this.operands_fra = new Fractions[operators_num+1];
     30         this.init();
     31     }
     32     //初始化各种参数
     33     private void init(){
     34         Random random=new Random();
     35         if(operators_num==1)
     36             bracketNum=0;
     37         else
     38             bracketNum=random.nextInt(operators_num/2+operators_num%2+1);
     39         leftBracket = new int[operators_num];
     40         rightBracket = new int[operators_num];
     41         priStack = new Stack<Character>();
     42         numStack = new Stack<Fractions>();
     43         initBracketArray();
     44         if(bracketNum>0){
     45         for(int i=0;i<this.bracketNum;i++){
     46             int pos = random.nextInt(operators_num);
     47             leftBracket[pos]++;
     48             rightBracket[random.nextInt(operators_num-pos)+pos]++;
     49 
     50         }
     51         checkBracket();
     52         }
     53         for(int i=0;i<this.operands.length;i++){
     54             operands[i]=random.nextInt(100)+1;
     55         }
     56         for(int i=0;i<this.operands_fra.length;i++){
     57             operands_fra[i]=new Fractions(operands[i],1);
     58         }
     59         for(int i=0;i<this.operators.length;i++){
     60             switch(random.nextInt(4)){
     61             case 0:
     62                 operators[i]='+';
     63                 break;
     64             case 1:
     65                 operators[i]='-';
     66                 break;
     67             case 2:
     68                 operators[i]='*';
     69                 break;
     70             case 3:
     71                 operators[i]='/';
     72                 break;
     73             }
     74         }
     75         this.setExpression(printQuestion());
     76         this.calculate();
     77     }
     78     //初始化括号数组
     79     private void initBracketArray(){
     80         for(int i=0;i<this.operators_num;i++){
     81             leftBracket[i]=0;
     82             rightBracket[i]=0;
     83         }
     84     }
     85     //检查括号是否满足约束,不满足删除括号
     86     private boolean checkBracket(){
     87         boolean flag = true;
     88         int[] lb = leftBracket.clone();
     89         int[] rb = rightBracket.clone();
     90         for(int i=0;i<operators_num;i++){
     91             int temp =i;
     92             while(rb[i]>0){
     93                 for(int j=i;j>-1;j--){
     94                     while(lb[j]>0&&rb[i]>0){
     95                         lb[j]--;
     96                         rb[i]--;
     97                         if(temp-1==j||temp==j||(i==operators_num-1&&j==0)){
     98                             deleteBracket(j, i);
     99                             flag = false;
    100                         }
    101                         temp=j;
    102                     }
    103                 }
    104             }
    105         }
    106         return flag;
    107     }
    108     //删除括号
    109     private boolean deleteBracket(int lb,int rb){
    110         if(leftBracket[lb]==0||rightBracket[rb]==0)
    111             return false;
    112         leftBracket[lb]--;
    113         rightBracket[rb]--;
    114         bracketNum--;
    115         return true;
    116     }
    117     //打印表达式字符串
    118     private String printQuestion(){
    119         String str="";
    120         for(int i=0;i<operators_num;i++){
    121             for(int j=0;j<leftBracket[i];j++){
    122                 str+="(";
    123             }
    124             str+=operands[i];
    125             if(i>0){
    126                 for(int j=0;j<rightBracket[i-1];j++){
    127                     str+=")";
    128                 }
    129             }
    130             str+=operators[i].toString();
    131         }
    132         str+=operands[operators_num];
    133         if(bracketNum>0)
    134         for(int j=0;j<rightBracket[operators_num-1];j++){
    135             str+=")";
    136         }
    137         str+="=";
    138         return str;
    139     }
    140     //计算表达式
    141     private void calculate(){
    142         numStack.push(operands_fra[0]);
    143         int i=0;
    144         int[] lb = leftBracket.clone();
    145         int[] rb = rightBracket.clone();
    146         while(i<operators_num){
    147             while(lb[i]>0){
    148                 priStack.push('(');
    149                 lb[i]--;
    150             }
    151             if(i>0){
    152                 if(rb[i-1]>0){
    153                     char ope = priStack.pop();
    154                     if(ope=='(')
    155                         continue;
    156                     Fractions b = (Fractions) numStack.pop();// 第二个运算数
    157                     Fractions a = (Fractions) numStack.pop();// 第二个运算数
    158                     Fractions tempresult ;
    159                     switch (ope) {
    160                     // 如果是加号或者减号,则   
    161                     case '+':
    162                         tempresult = Calculate.addtion(a, b);
    163                         numStack.push(tempresult);
    164                         break;
    165                     case '-':
    166                         tempresult = Calculate.subtraction(a, b);
    167                         numStack.push(tempresult);
    168                         break;
    169                     case '*':
    170                         tempresult = Calculate.multiplication(a, b);
    171                         numStack.push(tempresult);
    172                         break;
    173                     case '/':
    174                         tempresult = Calculate.division(a, b);
    175                         numStack.push(tempresult);
    176                         break;
    177                     }
    178                     rb[i-1]--;
    179                 }
    180             }
    181             if(!compare(operators[i])){
    182                 Fractions b = (Fractions) numStack.pop();// 第二个运算数
    183                 Fractions a = (Fractions) numStack.pop();// 第二个运算数
    184                 char ope = priStack.pop();
    185                 Fractions tempresult ;
    186                 switch (ope) {
    187                 // 如果是加号或者减号,则   
    188                 case '+':
    189                     tempresult = Calculate.addtion(a, b);
    190                     numStack.push(tempresult);
    191                     break;
    192                 case '-':
    193                     tempresult = Calculate.subtraction(a, b);
    194                     numStack.push(tempresult);
    195                     break;
    196                 case '*':
    197                     tempresult = Calculate.multiplication(a, b);
    198                     numStack.push(tempresult);
    199                     break;
    200                 case '/':
    201                     tempresult = Calculate.division(a, b);
    202                     numStack.push(tempresult);
    203                     break;
    204                 }
    205             }else{
    206                 priStack.push(operators[i]);
    207                 numStack.push(operands_fra[i+1]);
    208                 i++;
    209             }
    210         }
    211         while(!priStack.isEmpty()){
    212             char ope = priStack.pop();
    213             if(ope=='(')
    214                 continue;
    215             Fractions b = (Fractions) numStack.pop();// 第二个运算数
    216             Fractions a = (Fractions) numStack.pop();// 第一个运算数
    217             Fractions tempresult ;
    218             switch (ope) {
    219             // 如果是加号或者减号,则   
    220             case '+':
    221                 tempresult = Calculate.addtion(a, b);
    222                 numStack.push(tempresult);
    223                 break;
    224             case '-':
    225                 tempresult = Calculate.subtraction(a, b);
    226                 numStack.push(tempresult);
    227                 break;
    228             case '*':
    229                 tempresult = Calculate.multiplication(a, b);
    230                 numStack.push(tempresult);
    231                 break;
    232             case '/':
    233                 tempresult = Calculate.division(a, b);
    234                 numStack.push(tempresult);
    235                 break;
    236             }
    237         }
    238 
    239         result = numStack.pop();
    240     }
    241     private boolean compare(char str) {   
    242         if (priStack.empty()) {   
    243           // 当为空时,显然 当前优先级最低,返回高   
    244           return true;   
    245         }   
    246         char last = (char) priStack.lastElement();   
    247         // 如果栈顶为'('显然,优先级最低,')'不可能为栈顶。   
    248         if (last == '(') {   
    249           return true;   
    250         }   
    251         switch (str) {   
    252         case '=':   
    253           return false;// 结束符   
    254         case '(':   
    255           // '('优先级最高,显然返回true   
    256           return true;   
    257         case ')':   
    258           // ')'优先级最低,   
    259           return false;   
    260         case '*': {   
    261           // '*/'优先级只比'+-'高   
    262           if (last == '+' || last == '-')   
    263             return true;   
    264           else  
    265             return false;   
    266         }   
    267         case '/': {   
    268           if (last == '+' || last == '-')   
    269             return true;   
    270           else  
    271             return false;   
    272         }   
    273           // '+-'为最低,一直返回false   
    274         case '+':   
    275           return false;   
    276         case '-':   
    277           return false;   
    278         }   
    279         return true;   
    280       }
    281     public Fractions getResult() {
    282         return result;
    283     }
    284     public String getExpression() {
    285         return expression;
    286     }
    287     private void setExpression(String expression) {
    288         this.expression = expression;
    289     }  
    290 
    291 }
    Question

    6.2Calculate类如下:

     1 package calculate;
     2 
     3 import fraction.Fractions;
     4 public  class Calculate {
     5    
     6     public Calculate(){
     7     }
     8     // 加法计算
     9     public static Fractions addtion(Fractions fractions1,Fractions fractions2)
    10     {
    11         int result_numerator,min;  // 相加后的分子以及两分数分母的最小公倍数
    12         min=Fractions.minCommonMultiple(fractions1.getDenominator(), fractions2.getDenominator());
    13         result_numerator=(min/fractions1.getDenominator())*fractions1.getNumerator()+(min/fractions2.getDenominator())*fractions2.getNumerator();
    14         Fractions result=new Fractions(result_numerator, min);
    15         return result;
    16     }
    17     // 减法计算
    18     public static Fractions subtraction(Fractions fractions1,Fractions fractions2)
    19     {
    20         int result_numerator,min;  // 相减后的分子以及两分数分母的最小公倍数
    21         min=Fractions.minCommonMultiple(fractions1.getDenominator(), fractions2.getDenominator());
    22         result_numerator=(min/fractions1.getDenominator())*fractions1.getNumerator()-(min/fractions2.getDenominator())*fractions2.getNumerator();
    23         Fractions result=new Fractions(result_numerator, min);
    24         return result;
    25     }
    26     // 乘法计算
    27     public static Fractions multiplication(Fractions fractions1,Fractions fractions2)
    28     {
    29         int result_numerator,result_denominator;  // 相乘后的分子和分母
    30         result_numerator=fractions1.getNumerator()*fractions2.getNumerator();
    31         result_denominator=fractions1.getDenominator()*fractions2.getDenominator();
    32         Fractions result=new Fractions(result_numerator, result_denominator);
    33         return result;
    34     }
    35     // 除法计算
    36     public static Fractions division(Fractions fractions1,Fractions fractions2)
    37     {
    38         int result_numerator,result_denominator;  // 相除后的分子和分母
    39         // 分数相除问题转换成分数相乘问题
    40         result_numerator=fractions1.getNumerator()*fractions2.getDenominator();
    41         result_denominator=fractions1.getDenominator()*fractions2.getNumerator();
    42         Fractions result=new Fractions(result_numerator, result_denominator);
    43         return result;
    44     }
    45 }
    Calculate

    6.3Control类如下:

    package control;
    
    import java.util.Random;
    import java.util.Scanner;
    
    import fraction.Fractions;
    import question.Question;
    
    public class Control {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            System.out.println("本次共有"+args[1]+"道题。");
            if(args[0].equals("-n")){
                Scanner scanner=new Scanner(System.in);
                Integer num=new Integer(args[1]);
                int correct=0;
                String answer[]=new String[num];//用户输入的答案
                Random random = new Random();
                boolean judge[] = new boolean[num];//保存用户输入对错
                Question[] questions = new Question[num];
                for(int i=0;i<num;i++){
                    questions[i] = new Question(random.nextInt(10)+1);
                    System.out.print((i+1)+":"+questions[i].getExpression());
                    answer[i] = scanner.nextLine();
                    Fractions result = questions[i].getResult();
                    int result_int = result.changeToInteger();
                    if(!answer[i].equals("")){
                    if(result_int!=Integer.MAX_VALUE){
                        if(Integer.parseInt(answer[i])==result_int){
                            judge[i]=true;
                            System.out.println("正确!");
                            correct++;
                        }else{
                            judge[i]=false;
                            System.out.println("不正确!正确答案:"+result_int);
                        }
                    }else{
                        String splits[] = answer[i].split("/");
                        if(splits.length==2&&Integer.parseInt(splits[0])==result.getNumerator()&&Integer.parseInt(splits[1])==result.getDenominator()){
                            judge[i]=true;
                            System.out.println("正确!");
                            correct++;
                        }else{
                            judge[i]=false;
                            System.out.println("不正确!正确答案:"+result.printFraction());
                        }
                    }
                    }else{
                        judge[i]=false;
                        System.out.println("未回答!正确答案:"+result.printFraction());
                    }
                }
                double score = (double)correct/(double)num*100.00;
                System.out.println("本次得分:"+score);
                scanner.close();
            }else{
                System.out.println("命令有误");
            }
    
        }
    
    }
    Control

    6.4Fractions类如下:

     1 package fraction;
     2 
     3 public class Fractions {
     4     private int numerator;  //分子
     5     private int denominator;  //分母
     6     // 无参数构造器
     7     public Fractions(){
     8     }
     9     //参数构造器
    10     public Fractions(int numerator,int denominator){
    11         this.setValue(numerator, denominator);
    12     }
    13     // 设置分子分母
    14     public void setValue(int numerator,int denominator)
    15     {
    16         if(numerator==0){
    17             this.numerator=0;
    18             this.denominator=1;
    19             return;
    20         }
    21         if(denominator==0){
    22             System.out.println("Error:denominator equals zero!");
    23         }
    24         int temp=maxCommonDivisor(denominator, numerator);  //temp为最大公约数
    25         this.numerator=numerator/temp;
    26         this.denominator=denominator/temp;
    27     }
    28     // 求最大公约数
    29     public static int maxCommonDivisor(int d, int n) 
    30     {  
    31         if (d < n) {// 保证d>n,若d<n,则进行数据交换  
    32             int temp = d;  
    33             d = n;  
    34             n = temp;  
    35         }  
    36         while (d % n != 0) {// 在余数不能为0时,进行循环  
    37             int temp = d % n;  
    38             d = n;  
    39             n = temp;  
    40         }  
    41         return n;// 返回最大公约数  
    42     }
    43     // 求最小公倍数
    44     public static int minCommonMultiple(int m, int n) {  
    45         return m * n / maxCommonDivisor(m, n);  
    46     }  
    47     // 打印分数
    48     public String printFraction()
    49     {
    50         return (this.numerator+"/"+this.denominator).toString();
    51     }
    52     // 获取分子
    53     public int getNumerator()
    54     {
    55         return this.numerator;
    56     }
    57     // 获取分母
    58     public int getDenominator()
    59     {
    60         return this.denominator;
    61     }
    62     //判断是否可以转化为整数
    63     private boolean isInteger(){
    64         if(this.denominator==1||this.denominator==-1)
    65             return true;
    66         else return false;
    67     }
    68     //转换为整数
    69     public int changeToInteger(){
    70         if(this.isInteger())
    71             return this.getNumerator();
    72         else 
    73             return Integer.MAX_VALUE;
    74     }
    75 }
    Fractions

    7.测试运行

    7.1程序测试

      程序截图如下:

      由上图可知,程序界面显示没问题,满足需求,括号也满足了嵌套,数学约束,结果由人工手算也是正确的。当然,这张图只是程序跑一次的结果,这个程序我跑了50次左右,结果都是正确(其中出BUG的部分也被修补过了)。在运行中,一开始结果是不正确的,错误集中在calculate()函数中,栈的入栈出栈顺序有问题,编程的时候没发现,发现错误的时候很难找出来。在括号数学约束中,bug也是很多的,会出现(34)+23这样的表达式,这段代码我看了很多遍,一直都没发现错误,后来才发现是少减了1,(⊙﹏⊙)b这个bug我纠结了2个小时。

    7.2单元测试

    7.2.1Calculate功能测试

      先展示单元测试的结果图:

      在此次单元测试中,分别测试了Calculate类中加减乘除的运算,例如:测试加法函数,输入(1/2+1/2),对比结果是否为1。具体测试类如下:

     1 package calculate;
     2 
     3 import static org.junit.Assert.*;
     4 
     5 import org.junit.Before;
     6 import org.junit.Test;
     7 
     8 import fraction.Fractions;
     9 
    10 public class CalculateTest {
    11 
    12     @Before
    13     public void setUp() throws Exception {
    14     }
    15 
    16     @Test
    17     public void testAddtion() {
    18         Fractions result = Calculate.addtion(new Fractions(1,2), new Fractions(1,2));
    19         assertEquals(1, result.getNumerator());
    20         assertEquals(1, result.getDenominator());
    21     }
    22 
    23     @Test
    24     public void testSubtraction() {
    25         Fractions result = Calculate.subtraction(new Fractions(1,2), new Fractions(1,2));
    26         assertEquals(0, result.getNumerator());
    27         assertEquals(1, result.getDenominator());
    28     }
    29 
    30     @Test
    31     public void testMultiplication() {
    32         Fractions result = Calculate.multiplication(new Fractions(1,2), new Fractions(1,2));
    33         assertEquals(1, result.getNumerator());
    34         assertEquals(4, result.getDenominator());
    35     }
    36 
    37     @Test
    38     public void testDivision() {
    39         Fractions result = Calculate.division(new Fractions(1,2), new Fractions(1,2));
    40         assertEquals(1, result.getNumerator());
    41         assertEquals(1, result.getDenominator());
    42     }
    43 
    44 }

    7.2.2Fractions功能测试

      Fractions类的测试结果如图:

      在Fractions中主要测试的是最大公约数,最小公倍数函数,分数转整数,打印分数,设置分数值。代码如下:

     1 package fraction;
     2 
     3 import static org.junit.Assert.*;
     4 
     5 import org.junit.Before;
     6 import org.junit.Test;
     7 
     8 public class FractionsTest {
     9     
    10     private  Fractions fraction;
    11 
    12     @Before
    13     public void setUp() throws Exception {
    14         fraction = new Fractions(1,1);
    15     }
    16 
    17     @Test
    18     public void testSetValue() {
    19         fraction.setValue(2, 3);
    20         assertEquals(2, fraction.getNumerator());
    21         assertEquals(3, fraction.getDenominator());
    22     }
    23 
    24     @Test
    25     public void testMaxCommonDivisor() {
    26         int divisor = fraction.maxCommonDivisor(9, 6);
    27         assertEquals(3, divisor);
    28     }
    29 
    30     @Test
    31     public void testMinCommonMultiple() {
    32         int multiple = fraction.minCommonMultiple(9, 6);
    33         assertEquals(18, multiple);
    34     }
    35 
    36     @Test
    37     public void testPrintFraction() {
    38         assertEquals("1/1", fraction.printFraction());
    39     }
    40 
    41     @Test
    42     public void testChangeToInteger() {
    43         assertEquals(1, fraction.changeToInteger());
    44     }
    45 
    46 }

     7.3代码覆盖测试

      代码覆盖测试使用的是EclEmma插件,运行结果截图如下:

      程序覆盖率在82%,其中有一些是判断失败的语句以及一些表达式并没有生成括号,所以一些代码没有运行到。

    8.实际花费的时间

    PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
    Planning 计划  10  30
    · Estimate · 估计这个任务需要多少时间  10  30
    Development 开发  360  600 
    · Analysis · 需求分析 (包括学习新技术)  30  30
    · Design Spec · 生成设计文档  20  60
    · Design Review · 设计复审 (和同事审核设计文档)  10  10
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范)  10  10
    · Design · 具体设计  30  30
    · Coding · 具体编码  230  420
    · Code Review · 代码复审  20  10
    · Test · 测试(自我测试,修改代码,提交修改)  10  30
    Reporting 报告  60  360
    · Test Report · 测试报告  30  330
    · Size Measurement · 计算工作量  10  10
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划  20  20
    合计    430  990

    9.项目小结

      此次项目帮助我深入了解了PSP的工作流程,从计划、开发到测试,每一步都亲身体验,从中学到了许多,掌握了很多Eclipse的插件,比如:Eclipse自带的Git插件、GEF插件、单元测试等。我深刻体会到软件工程的系统性和复杂性,正如:

    软件工程是一门研究用工程化方法构建和维护有效的、实用的和高质量的软件的学科。它涉及程序设计语言、数据库、软件开发工具、系统平台、标准、设计模式等方面。
    在现代社会中,软件应用于多个方面。典型的软件有电子邮件、嵌入式系统、人机界面、办公套件、操作系统、编译器、数据库、游戏等。同时,各个行业几乎都有计算机软件的应用,如工业、农业、银行、航空、政府部门等。这些应用促进了经济和社会的发展,也提高了工作效率和生活效率 。

      由于一开始没有单元测试的概念,导致单元测试都是在完成整个软件的时候才开始的。单元测试应该在完成每一个功能模块的时候就进行,这样才能保证每一个功能的正确性。并且在更改和更新的时候还需要做回归测试,保证原有功能正常,不受新功能的影响。

  • 相关阅读:
    退背包
    杜教筛BM
    Petya and Array CodeForces
    AC自动机模板
    KMP模板
    Docker系列器九:docker-compose与docker-compose.yml语法
    Fabric的简单Web应用
    ubuntu防火墙
    ubuntu16.04 HyperLedger Fabric 1.2.0 开发环境搭建
    crypto-config.yaml
  • 原文地址:https://www.cnblogs.com/zgjssqchy/p/7581037.html
Copyright © 2020-2023  润新知