使用Intellij来练习测试驱动开发 TDD Kata

文章目录

  • 使用Intellij来练习测试驱动开发 TDD Kata
    • 前言
    • 创建Java Maven项目
    • TheBowlingGame Kata
      • The Requirements
      • Step1: 创建项目
      • Step2: 新建测试类
      • Step3: 编写第1个测试方法
      • Step4: 运行测试
      • Step5: 修复编译错误
      • Step6: 再次运行测试
      • Step7: 继续修改测试方法
      • Step8: 修复编译错误
      • Step9: 编写第2个测试方法
      • Step10: 修复测试失败
      • Step11: 重构测试类
      • Step12: 继续重构测试类
      • Step12: 编写第3个测试方法
      • Step13: 修复测试失败
      • Step14: 继续修复测试失败
      • Step15: 重构实现类
      • Step16: 重构测试类
      • Step17: 编写第4个测试方法
      • Step18: 修复测试失败
      • Step19: 重构实现类
      • Step20: 继续重构实现类
      • Step21: 继续重构实现类
      • Step22: 继续重构实现类
      • Step23: 重构测试类
      • Step24: 编写第5个测试方法
      • Step25: 重构实现类
    • TDD Kata小结
    • Intellij常用快捷键
    • 如何提升打字速度
    • 参考文档

使用Intellij来练习测试驱动开发 TDD Kata

前言

本文描述了如何使用Intellij来练习测试驱动开发(TDD Kata)。

编程环境:

  • Intellij IDEA 2019.3 (Mac版)
  • Java 8
  • Maven 3.6(配置使用阿里云Maven镜像)
  • JUnit 4

创建Java Maven项目

IDEA中创建一个标准的含有JUnit的Java Maven项目的过程如下:

  1. File / New Project / Maven;
  2. 勾选"Create from archetype",选择org.apache.maven.archetypes:maven-archetype-quickstart
  3. 输入Name为项目名称,选择Location为项目路径,展开Artifact Coordinates,输入GroupId为包路径,ArtifactId默认为项目名称;
  4. 确认信息无误后,开始创建项目;
  5. 点击“Open Windows”打开项目;
  6. 在弹出框中选择“Enable Auto-Import”;
  7. 编辑项目pom.xml,将maven.compiler.sourcemaven.compiler.target改为1.8
  8. 右键选择项目,Maven / Reimport;
  9. 删除自动生成的App和AppTest类。

也可以自定义Maven archetype,通用运行Maven命令一键生成项目。

TheBowlingGame Kata

以Bob大叔的Bowling Game Kata为例,讲解如何通过IDEA来练习TDD Kata。

  • TheBowlingGameKata

保龄球比赛计分规则:

  • 保龄球的计分不难,每一局(Game)总共有十格(Frame),每一格里面有两次投球(Roll)。

  • 共有十支球瓶,要尽量在两次投球之内把球瓶(Pin)全部击倒,如果第一球就把全部的球瓶都击倒了,也就是“STRIKE”,画面出现“X”,就算完成一格了,所得分数就是10分再加下两球的倒瓶数。

  • 但是如果第一球没有全倒时,就要再打一球,如果剩下的球瓶全都击倒,也就是“SPARE”,画面出现“/”,也算完成一格,所得分数为10分再加下一格第一球的倒瓶数。

  • 但是如果第二球也没有把球瓶全部击倒的话,那分数就是第一球加第二球倒的瓶数,再接着打下一格。

  • 依此类推直到第十格,但是第十格有三球,第十格时如果第一球或第二球将球瓶全部击倒时,可再加打第三球。

参见:

  • 保龄球百度百科

在练习时只使用英文输入法,避免频繁切换输入法,和避免在中文输入法时IDEA快捷键不生效。

The Requirements

Write a class named Game that has two methods:

  • roll(pins : int) is called each time the player rolls a ball.The argument is the number of pins knocked down.
  • score() : int is called only at the very end of the game. It returns the total score for that game.

Step1: 创建项目

参见上面的“创建Java Maven项目”章节来创建项目:

  • 项目名称:bowling-game-kata
  • GroupId: cn.xdevops.kata
  • ArtifactId: bowling-game-kata

Step2: 新建测试类

/src/test/java/cn.xdevops.kata目录下创建测试类GameTest。

选择/src/test/java/cn.xdevops.kata目录:

# 新建
Ctrl + N

# 默认选择新建Java Calss
Enter

# 输入类名
GameTest

# 确认新建
Enter

# 光标跳到下一行
Shift + Enter

Step3: 编写第1个测试方法

编写一个最差的比赛结果(每次投球都没有击倒瓶子)的测试方法:

@Test
public void testGutterGame() {
  Game game = new Game();
}

因为Game类还没有创建,此时有编译错误,先忽略。

Step4: 运行测试

将光标移动到GameTest类名一行:

# 运行测试
Shift + F10

因为Game类还没有创建,此时有编译错误,所以测试失败(红)。

Step5: 修复编译错误

将光标移动到Game类名上:

# 自动修复错误
Alter + Enter

# 默认选择Create class
Enter

# 确认生成类
Enter

Step6: 再次运行测试

# 运行测试
Shift + F10

此时,测试通过(绿)。

Step7: 继续修改测试方法

切换回测试类GameTest:

# 切换类
Command + E

# 切换为上一个打开的类
Enter

在测试方法中增加逻辑:

@Test
public void testGutterGame() {
  Game game = new Game();
  for (int i = 0; i < 20; i ++) {
    game.roll(0);
  }
  assertEquals(0, game.score());
}

Step8: 修复编译错误

因为有很明显的编译错误,所以我们不再运行测试类,而是先修复编译错误。

Alt + Enter来修复编译错误:

  • Game类中创建roll()方法,修改参数名为pins
  • 引入assertEquals
  • Game类中创建score()方法,返回值为0

代码示例:

public class Game {
    public void roll(int pins) {
    }

    public int score() {
        return 0;
    }
}

按下Shift + F10运行测试,测试通过(绿)。

Step9: 编写第2个测试方法

增加一个简单的测试方法,假设每次投球都击倒1个瓶子。

有了前面的经验,我们可以很快地写出这个测试方法。

代码示例:

@Test
public void testAllOnes() {
  Game game = new Game();
  for (int i = 0; i < 20; i ++) {
    game.roll(1);
  }
  assertEquals(20, game.score());
}

按下Shift + F10运行测试,因为我们还没有实现该功能,测试失败(红)。

Step10: 修复测试失败

很容易想到,只要将每次投球击倒的瓶子数量累加来作为最后的分数就可以了。

代码示例:

public class Game {
    private int score = 0;

    public void roll(int pins) {
        score += pins;
    }

    public int score() {
        return score;
    }
}

按下Shift + F10运行测试,测试通过(绿)。

Step11: 重构测试类

因为测试类中存在了重复代码,因此在继续编写新的测试方法前,需要先重构测试类。

将每个测试方法中的创建Game实例的语句抽取出来,写成JUnit的setUp()方法。

public class GameTest {

    private Game game;

    @Before
    public void setUp() {
        game = new Game();
    }

    @Test
    public void testGutterGame() {
        for (int i = 0; i < 20; i ++) {
            game.roll(0);
        }
        assertEquals(0, game.score());
    }

    @Test
    public void testAllOnes() {
        for (int i = 0; i < 20; i ++) {
            game.roll(1);
        }
        assertEquals(20, game.score());
    }
}

按下Shift + F10运行测试,确保在重构后,测试仍然通过(绿)。

Step12: 继续重构测试类

将测试类中的扔20个球,每个球都击倒一样瓶子的方法抽取成一个方法:

# 选择重复代码

# 提取方法
Alt + Comand + M

# 输入方法
rollMany

# Refactor
Enter

# 选择使用原方法签名或接受推荐的方法签名
Enter

# 选择是否替换其他重复代码
Enter

修改rollMany()方法,支持传入指定的球数,并修改方法参数(Shift + F6

private void rollMany(int rolls, int pins) {
  for (int i = 0; i < rolls; i++) {
    game.roll(pins);
  }
}

修改调用rollMany()方法的语句,传入指定的球数为20。

完整代码:

public class GameTest {

    private Game game;

    @Before
    public void setUp() {
        game = new Game();
    }

    @Test
    public void testGutterGame() {
        rollMany(20, 0);
        assertEquals(0, game.score());
    }

    private void rollMany(int rolls, int pins) {
        for (int i = 0; i < rolls; i++) {
            game.roll(pins);
        }
    }

    @Test
    public void testAllOnes() {
        rollMany(20, 1);
        assertEquals(20, game.score());
    }
}

按下Shift + F10运行测试,确保在重构后,测试仍然通过(绿)。

Step12: 编写第3个测试方法

增加一个测试方法,来测试第一个Frame为Spare的情况。

@Test
public void testOneSpare() {
  game.roll(4);
  game.roll(6); // spare
  game.roll(3);
  rollMany(17, 0);
  assertEquals(16, game.score());
}

在这个例子中,第一个Frame为Spare,所以第一个Frame的得分要加上该Frame的下一个球击倒的球数(Spare bonus)。为简单起见,假设后面17个球都没有击倒瓶子。

按下Shift + F10运行测试,测试失败(红),因为Game类还没有考虑加上Spare bonus的情况。

Step13: 修复测试失败

在保龄球比赛中:

  • 如果一个Frame是Spare,该Frame的得分要加上下一个球击倒的瓶子数(Spare bonus);
  • 如果一个Frame是Strike,该Frame的得分要加上下两个球击倒的瓶子数(Strike bonus)。

所以,我们首先要记住每次投球所击倒的瓶子数,因为最多投球21次(每Frame最多投2球,最后一个Frame最多投3个球),所以用一个长度为21的int数组来记。

再用一个变量来记住当前是第几个球。

代码示例:

private int[] rolls = new int[21];
private int currentRoll = 0;

在每次投球时记住该次投球击倒的瓶子数,并记录当前是第几个球:

public void roll(int pins) {
  rolls[currentRoll] = pins;
  currentRoll ++;
}

在计算比赛得分时,累加全部球击倒的瓶子数加上Spare bonus和Strike bonus。

先累加全部球击倒的瓶子数:

public class Game {
    private int[] rolls = new int[21];
    private int currentRoll = 0;

    public void roll(int pins) {
        rolls[currentRoll] = pins;
        currentRoll ++;
    }

    public int score() {
        int score = 0;
        for (int i = 0; i < rolls.length;i ++) {
            score += rolls[i];
        }
        return score;
    }
}

按下Shift + F10运行测试,发现其他不需要计算bonus的测试方法测试通过,但是需要计算Spare bonus的方法仍然测试不通过。

Step14: 继续修复测试失败

继续实现计算Spare bonus的逻辑:

  • Spare时,该Frame的得分为10分加上下一次投球击倒的瓶子数;
  • 其他情况时,该Frame的得分为两次投球击倒的瓶子总数。(先不考虑Strike的情况)
public int score() {
  int score = 0;
  int rollIndex = 0;
  for (int frame = 0; frame < 10; frame ++) {
    if (rolls[rollIndex] + rolls[rollIndex + 1] == 10) {
      // spare: sum of balls in frame is 10
      // spare bonus: balls of next roll
      score += 10 + rolls[rollIndex + 2];
      // move to next frame
      rollIndex += 2;
    } else {
      // other: sum of balls in frame
      score += rolls[rollIndex] + rolls[rollIndex + 1];
      // move to next frame
      rollIndex += 2;
    }
  }
  return score;
}

按下Shift + F10运行测试,测试通过(绿)。

Step15: 重构实现类

重构Game类的score()方法,去除注释,让代码能够“自描述”。

提取出一个专门的方法用来判断是否为Spare:

 private boolean isSpare(int rollIndex) {
   return rolls[rollIndex] + rolls[rollIndex + 1] == 10;
 }

按下Shift + F10运行测试,测试通过(绿)。

去掉Spare部分的注释:

public int score() {
  int score = 0;
  int rollIndex = 0;
  for (int frame = 0; frame < 10; frame++) {
    if (isSpare(rollIndex)) {
      score += 10 + rolls[rollIndex + 2];
      // move to next frame
      rollIndex += 2;
    } else {
      // other: sum of balls in frame
      score += rolls[rollIndex] + rolls[rollIndex + 1];
      // move to next frame
      rollIndex += 2;
    }
  }
  return score;
}

按下Shift + F10运行测试,测试通过(绿)。

Step16: 重构测试类

重构GameTest类的testOneSpare()方法。

提取出一个专门的rollSpare()方法。

private void rollSpare() {
  game.roll(4);
  game.roll(6);
}

按下Shift + F10运行测试,测试通过(绿)。

重构后的testOneSpare()方法:

@Test
public void testOneSpare() {
  rollSpare();
  game.roll(3);
  rollMany(17, 0);
  assertEquals(16, game.score());
}

Step17: 编写第4个测试方法

增加一个测试方法,来测试第一个Frame为Strike的情况。

@Test
public void testOneStrike() {
  game.roll(10); // strike
  game.roll(3);
  game.roll(4);
  rollMany(16, 0);
  assertEquals(24, game.score());
}

在这个例子中,第一个Frame为Strike,所以第一个Frame的得分要加上该Frame的下两个球击倒的球数(Strike bonus)。为简单起见,假设后面16个球都没有击倒瓶子。

按下Shift + F10运行测试,测试失败(红),因为Game类还没有考虑加上Strike bonus的情况。

Step18: 修复测试失败

增加计算Strik bonus的情况,并完善注释。

public int score() {
  int score = 0;
  int rollIndex = 0;
  for (int frame = 0; frame < 10; frame++) {
    if (rolls[rollIndex] == 10) {
      score += 10 + rolls[rollIndex + 1] + rolls[rollIndex + 2];
      rollIndex += 1;
    } else if (isSpare(rollIndex)) {
      score += 10 + rolls[rollIndex + 2];
      // move to next frame
      rollIndex += 2;
    } else {
      // other: sum of balls in frame
      score += rolls[rollIndex] + rolls[rollIndex + 1];
      // move to next frame
      rollIndex += 2;
    }
  }
  return score;
}

按下Shift + F10运行测试,测试通过(绿)。

Step19: 重构实现类

提取出一个专门的方法用来判断是否为Strike:

private boolean isStrike(int rollIndex) {
  return rolls[rollIndex] == 10;
}

按下Shift + F10运行测试,测试通过(绿)。

Step20: 继续重构实现类

提取出一个专门的方法用来计算Strike bonus。

private int strikeBonus(int rollIndex) {
  return rolls[rollIndex + 1] + rolls[rollIndex + 2];
}

按下Shift + F10运行测试,测试通过(绿)。

Step21: 继续重构实现类

提取出一个专门的方法用来计算Spare bonus。

private int spareBonus(int rollIndex) {
  return rolls[rollIndex + 2];
}

按下Shift + F10运行测试,测试通过(绿)。

Step22: 继续重构实现类

提取出一个专门的方法用来计算普通的Frame的得分。

private int sumOfBallsInFrame(int rollIndex) {
  return rolls[rollIndex] + rolls[rollIndex + 1];
}

按下Shift + F10运行测试,测试通过(绿)。

Step23: 重构测试类

重构GameTest类的testOneStrike()方法。

提取出一个专门的rollStrike()方法。

private void rollStrike() {
  game.roll(10);
}

按下Shift + F10运行测试,测试通过(绿)。

重构后的testOneStrike()方法:

@Test
public void testOneStrike() {
  rollStrike();
  game.roll(3);
  game.roll(4);
  rollMany(16, 0);
  assertEquals(24, game.score());
}

Step24: 编写第5个测试方法

增加一个测试方法,来测试最完美的情况,也就是连续12个球都把10个瓶子击倒了,该局比赛得分为300分。

@Test
public void testPerfectGame() {
  rollMany(12, 10);
  assertEquals(300, game.score());
}

按下Shift + F10运行测试,测试通过(绿)。

Step25: 重构实现类

将Game类的一些hardcode改为为常量。

直接将hardcode改为常量,再用Alt + Enter自动生成常量。

按下Shift + F10运行测试,测试通过(绿)。

重构后的代码:

package cn.xdevops.kata;

public class Game {
    private static final int MAX_ROLL_NUM = 21;
    private static final int MAX_FRAME_NUM = 10;
    private static final int MAX_PIN_NUM = 10;

    private int[] rolls = new int[MAX_ROLL_NUM];
    private int currentRoll = 0;

    public void roll(int pins) {
        rolls[currentRoll] = pins;
        currentRoll++;
    }

    public int score() {
        int score = 0;
        int rollIndex = 0;
        for (int frame = 0; frame < MAX_FRAME_NUM; frame++) {
            if (isStrike(rollIndex)) {
                score += MAX_PIN_NUM + strikeBonus(rollIndex);
                rollIndex += 1;
            } else if (isSpare(rollIndex)) {
                score += MAX_PIN_NUM + spareBonus(rollIndex);
                rollIndex += 2;
            } else {
                score += sumOfBallsInFrame(rollIndex);
                rollIndex += 2;
            }
        }
        return score;
    }

    private int sumOfBallsInFrame(int rollIndex) {
        return rolls[rollIndex] + rolls[rollIndex + 1];
    }

    private int spareBonus(int rollIndex) {
        return rolls[rollIndex + 2];
    }

    private int strikeBonus(int rollIndex) {
        return rolls[rollIndex + 1] + rolls[rollIndex + 2];
    }

    private boolean isStrike(int rollIndex) {
        return rolls[rollIndex] == MAX_PIN_NUM;
    }

    private boolean isSpare(int rollIndex) {
        return rolls[rollIndex] + rolls[rollIndex + 1] == MAX_PIN_NUM;
    }
}

至此,一个功能正确,且代码整洁的BowlingGame Kata就完成了。

TDD Kata小结

TDD心法小结;

  • 红-绿-重构,不断迭代;

  • 小步快跑(步子大了容易走火入魔)

  • 增加新功能时不重构,重构时不增加新功能

刚开始练习TDD Kata时步子要小,可以慢一点。等熟练后,就要刻意练习加快速度,可以用秒表来统计Kata用时。

一般来说一个Kata的用时,不应该超过1个番茄钟(25分钟)。可以通过以下方法提升速度:

  • 只用英文输入法,用英文写注释;
  • 熟悉Intellij快捷键操作,尽量少用鼠标;
  • 熟练掌握编程语言的语法和常用API(编程时不去搜索语法);
  • 平时有意练习打字速度;
  • 多多练习不同的Kata,用不同的编程语言来实现。

Intellij常用快捷键

编程中常用的快捷键:

名称 快捷键(Mac)
新建 Ctrl + N
切换 Command + E
自动修复 Alt + Enter
运行 Shift + F10
重命名 Shift + F6
提取方法 Alt + Command + M
提取变量 Alt + Command + V
光标跳到下一行 Shift + Enter
光标跳到行首 Fn + Left
光标跳到行尾 Fn + Right
注释/取消注释 Command + /
格式化 Alt + Command + L

按下CTRL + SHIFT + A快速查找相应Action (菜单)。

参见

  • Intellj快捷键官方文档

  • IDEA Windows快捷键

  • IDEA MacOS快捷键

如何提升打字速度

可以在https://typing.io/lessons上测试和练习多种编程语言的打字速度。

参考文档

  • https://www.jetbrains.com/help/idea/tdd-with-intellij-idea.html
  • https://www.jetbrains.com/help/idea/refactoring-source-code.html
  • 软件匠艺 Software Craftsmanship

热门文章

暂无图片
编程学习 ·

【MPI编程实现梯形积分法】

MPI编程实现梯形积分法1.1问题描述1.2算法实现1.3结果实现与分析1.4源码实现 1.1问题描述 实现课件中的梯形积分法的MPI编程熟悉并掌握MPI编程方法,规模自行设定,可探讨不同规模对不同实现方式的影响。实验环境:联想笔记本,集成开发环境:Visual Studio 1.2算法实现 每个进…
暂无图片
编程学习 ·

工科中的设计思维

超星学习通app工科中的设计思维网课答案,工科中的设计思维尔章节测验网课答案1.1 走近设计思维1【单选题】本门课程讲述的主要内容不包括()。A、设计思维这一学习形式和思维方式B、一系列有用的创新工具和创造技法C、工科学生需要用到的专业设计软件D、系统化的设计流程和与众…
暂无图片
编程学习 ·

服务器使用Nginx部署Springboot项目(jar包)

部署SpringBoot项目到后台Nginx实现多项目反向代理1,将java项目打成jar包2.准备工具3.将jar包传入服务器3.使用Xshell运行jar包4.下载安装nginx5.配置nginx.conf6通过域名访问(成功) 1,将java项目打成jar包 这里我用到的是maven工具这里有两个项目,打包完成后一个为demo.jar,另…
暂无图片
编程学习 ·

vue or h5分享页面 唤起和下载app(苹果和安卓判断 及 微信浏览器和其他浏览器的判断)

题外话: 菜鸡是没有发言权的,导致即使不是前端的锅,也把它变成是你的锅。 哎!!!!!!!!!!!!!首先必须感谢我认识的大佬,一直在帮我解决问题(我关注的那个jamesluozhiwei 这位)步入正题: 1 。唤起和下载 用的框架 和 参考文档(重要,弄清原理啥的看这个)…
暂无图片
编程学习 ·

lex yacc flex bison

简介 lex与yacc是两个在Unix下的分别作词法分析和语法分析的工具, Linux对应flex与bison。 Yacc 与 Lex 快速入门 flex 和bison的安装和使用 Windows下安装lex(flex)与yacc(bison)
暂无图片
编程学习 ·

Mathmatica多项式带余除法代码

几乎没有调用内置函数,除了求多项式最高次数时用了一下 Exponent[] (*解析多项式*) (*将f=a0+a1*x+...+an*x^n解析成{{a0,0},{a1,1},...,{an,n}}的形式*) polyCoefficients[f_] := Module[{rules1 = {c_*base_^power_ -> {c, power},base_^power_ -> {1, power},c_*x_ -…
暂无图片
编程学习 ·

python pytest selenium 自动化测试框架搭建

python pytest selenium 自动化测试框架搭建公司一直有这个自动化测试需求,前期利用c++或者python进行了一些自动化脚本的编写。这几天没有版本更迭,基于前期的工作,把自动化测试整理了一部分功能模块。现在的状态基本达到预期:即搭建了一个AutoTest框架,基于此实现了logi…
暂无图片
编程学习 ·

直播带货系统开发机遇与挑战并存

如今,直播带货正逐渐取代以往传统的营销方式,各大电商也因此纷纷踏入直播带货系统开发热门,开发出多个功能为一体的直播带货系统。2020年,面临着直播带货的空前盛况,不仅是直播带货系统开发的机遇,同时也是一个挑战。所谓的直播带货,顾名思义,就是商家以及直播通过直播…
暂无图片
编程学习 ·

Python——走马灯

走马灯 def f():import times=人生苦短,我学Pythonc=0while True:print(s)time.sleep(0.3)#休眠0.3秒。每隔0.3秒,即300毫秒显示一行代码s=s[1:]+s[0]c+= 1if c==2*len(s):break f()输出结果 人生苦短,我学Python 生苦短,我学Python人 苦短,我学Python人生 短,我学Python…
暂无图片
编程学习 ·

机器视觉打光技巧

光源专家的8个打光技巧 机器视觉系统中的照明系统是极其重要的一部分,它的好坏直接影响着后面的图像处理。在听了一位日本光源专家的讲座之前,我其实对照明并不太了解,不就是将图像照亮以至于相机能够拍到图像吗?但事实并非如此,照明远非增强图像亮度这样简单,好的照明系…
暂无图片
编程学习 ·

JS笔记(一)

1.JS基本类型:ECMAScript 中有5种简单数据类型(也称为基本数据类型):Undefined,Null,Boolean,Number和String。一种复杂数据类型:object# typeOf null 的结果为Objectvar n = null var flag = true var s = str var num = 11 var un = undefinedconsole.log(typeof(n)); …
暂无图片
编程学习 ·

maven 有时候parent项目版本没更新的版本问题

对于parent工程,一般规定了版本,并且包含了子模块。如果首次编译整个项目,可能导致编译不成功,因为子模块需要父工程版本号。父工程想连同子模块一起编译,所以首次编译的时候,注释掉parent工程的子模块。先编译版本,成功后放开子模块。就可以了。如果parent的版本发生变…
暂无图片
编程学习 ·

必应每日壁纸——7月

只分享,不科普 自行必应科普July1 Wednesday2 Thursday3 Friday4 Saturday5 Sunday6 Monday7 Tuesday8 Wednesday9 Thursday10 Friday11 Saturday12 Sunday July 1 Wednesday 班夫国家公园 莫兰湖德国卡塞尔威廉高地公园中的阿波罗神庙2 Thursday 3 Friday 4 Saturday 5 Sunda…
暂无图片
编程学习 ·

zabbix(三)对服务的监控

文章目录zabbix(三)对服务的监控httpd/nginxmysql zabbix(三)对服务的监控 httpd/nginx 1>给 server2 添加 httpd 监控 但是这个 http 监控的监控项只有一个,下面在 server3 上自定义 nginx 的监控#源码编译 nginx,关闭 debug,添加监控模块 [root@server3 nginx-1.15.8]#./c…
暂无图片
编程学习 ·

葡萄酒分类

#加载数据 df = pd.read_csv("winequality-red.csv") df.head() #空值 df.isnull().any() df.describe()# 简单的数据统计 # 总酸度,把固定酸,挥发酸,柠檬酸三项合起来定义一个新的特征总酸量。 df[total acid] = df[fixed acidity] + df[volatile acidity] + df[…
暂无图片
编程学习 ·

C#中常见的简答题(第三天)

8.简述ADO.NET中五个主要对象A.Connection:主要是开启程序和数据库之间的连接。没有利用连接对象将数据库打开,是无法从数据库中取得数据的。Close和Dispose的区别,Close以后还可以Open,Dispose以后则不能再用。B.Command:主要可以用来对数据库发出一些指令,例如可以对数据…
暂无图片
编程学习 ·

mxnet安装环境配置

一、安装Miniconda 官方网址:https://conda.io/en/latest/miniconda.html 本人选择python3.7版本Windows64位 安装完成后打开Anaconda Prompt创建虚拟环境conda create –n env python=3.7 这里的env为自定义环境名激活环境 conda activate env 退出环境: conda deactivate查…