2021-08-02 测试代码

Python标准库中的模块unittest提供了代码测试工具。单元测试用于核实函数的某个方面没有问题。测试用例是一组单元测试,他们一道核实函数在各种情形下的行为都符合要求。全覆盖的测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。

一、测试函数

1. 可通过的测试

要为函数编写测试用例,先导入模块unittest和要测试的函数,再创建一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。

import unittest
from name_function import get_formatted_name


class NamesTestCase(unittest.TestCase):
    def test_first_last_name(self):
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')

if __name__ == '__main__':
    unittest.main()

创建了名为NamesTestCase的类,用于包含一系列针对get_formatted_name()的单元测试。这个类可以随意命名,但最好让它看起来和要测试的函数相关并包含Test字样,这个类必须继承unittest.TestCase类,这样Python才知道如何运行。

运行这个python文件时,所有以test打头的方法都将自动运行。

assertEqual()是unittest类中最有用的功能之一,断言方法。断言方法核实得到的结果是否与期望的结果一致。

我们可以直接运行这个文件,但需要指出的是,很多测试框架都会先导入测试文件再运行。在本代码中,我们调用unittest.main()来运行测试用例。如果这个文件被测试框架导入,变量__name__的值将不是'__main__',也不会调用unitt.main()。

输出如下:

2. 未通过的测试 

 测试未通过时,不要修改测试,而应修复导致测试不能通过的代码:检查刚刚对函数所做的修改,找出导致函数行为不符合预期的修改。

3. 添加新测试

class NamesTestCase(unittest.TestCase):
    def test_first_last_name(self):
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')

    def test_first_last_middle_name(self):
        formatted_name = get_formatted_name('wolfgang', 'mozart', 'amadeus')
        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')

全部通过:

只错一个:

 二、测试类

1.各种断言方法

方法用途
assertEqual(a, b)核实a==b
assertNotEqual(a, b)核实a!=b
assertTrue(x)核实x为True
assertFalse(x)核实x为False
assertIn(item, list)核实item在list
assertNotIn(item, list)核实item不在list

2. 一个要测试的类

class AnonymousSurvey:
    def __init__(self, question):
        self.question = question
        self.responses = []

    def show_question(self):
        print(self.question)

    def store_response(self, response):
        self.responses.append(response)

    def show_results(self):
        print("Survey results:")
        for responce in self.responses:
            print(f" - {responce}")
import unittest
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
    def test_store_single_response(self):
        question = "What language did you first learn to speak?"
        my_survey = AnonymousSurvey(question)
        my_survey.store_response('English')
        self.assertIn('English', my_survey.responses)

    def test_store_three_responces(self):
        question = "What language did you first learn to speak?"
        my_survey = AnonymousSurvey(question)
        responses = ['English', 'Chinese', 'French']
        for response in responses:
            my_survey.store_response(response)
        for response in responses:
            self.assertIn(response, my_survey.responses)


if __name__ == '__main__':
    unittest.main()

如上。

3. 方法SetUp()

在测试一个类中,我们在每个测试方法中都创建了一个AnonymousSurvey实例,并在每个方法中都创建了答案。而SetUp()让我们只需要创建这些对象一次,就能在每个测试方法中使用。

import unittest
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
    def setUp(self):
        question = "What language did you first learn to speak?"
        self.my_survey = AnonymousSurvey(question)
        self.responses = ['English', 'Chinese', 'French']
    
    def test_store_single_response(self):
        self.my_survey.store_response(self.responses[0])
        self.assertIn('English', self.my_survey.responses)

    def test_store_three_responses(self):
        for response in self.responses:
            self.my_survey.store_response(response)
        for response in self.responses:
            self.assertIn(response, self.my_survey.responses)


if __name__ == '__main__':
    unittest.main()

setUp()创建了一个调查对象以及答案列表,存储这两样东西的变量名包含前缀self,即存储在属性中,因此可以在这个类的任何地方使用。

好的,以下是Java代码实现: ```java import java.time.LocalDate; import java.time.chrono.Chronology; import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoPeriod; import java.time.chrono.ChronologyType; import java.time.temporal.ChronoField; import java.time.temporal.TemporalAdjusters; import java.util.HashMap; public class LunarCalendar { // 二十四节气 private static final String[] solarTerms = { "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至", "小寒", "大寒" }; // 二十四节气对应的日期 private static final HashMap<String, LocalDate> solarTermMap = new HashMap<>(); // 初始化二十四节气对应的日期 static { Chronology lunarChronology = Chronology.of(ChronologyType.JAPANESE); ChronoLocalDate start = lunarChronology.date(2000, 1, 1); ChronoLocalDate end = lunarChronology.date(2023, 1, 1); ChronoPeriod period = ChronoPeriod.between(start, end); for (int i = 0; i < solarTerms.length; i++) { LocalDate solarTermDate = null; for (ChronoLocalDate date = start; !date.isAfter(end); date = date.plus(period)) { int year = date.get(ChronoField.YEAR); int month = date.get(ChronoField.MONTH_OF_YEAR); int day = date.get(ChronoField.DAY_OF_MONTH); LocalDate solarTerm = LocalDate.of(year, month, day); if (solarTerm.get(ChronoField.MONTH_OF_YEAR) != month) { solarTerm = solarTerm.with(TemporalAdjusters.lastDayOfMonth()); } if (solarTerms[i].equals(getSolarTerm(solarTerm))) { solarTermDate = solarTerm; break; } } solarTermMap.put(solarTerms[i], solarTermDate); } } // 获取某个日期对应的二十四节气 public static String getSolarTerm(LocalDate date) { int y = date.getYear(); int m = date.getMonthValue(); int d = date.getDayOfMonth(); if (d == getSolarTermDay(y, (m - 1) * 2)) { return solarTerms[(m - 1) * 2]; } if (d == getSolarTermDay(y, (m - 1) * 2 + 1)) { return solarTerms[(m - 1) * 2 + 1]; } return null; } // 获取某年某节气的日期 private static int getSolarTermDay(int year, int index) { double[] solarTermInfo = new double[]{0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758}; int[] solarTermDay = new int[24]; for (int i = 0; i < 24; i++) { solarTermDay[i] = (int) Math.round(solarTermInfo[i] + (31556925974.7 * (year - 2000) + 220250000) / Math.pow(2, (i * 2 + 1)) / 1000); } return solarTermDay[index]; } // 输出某年的二十四节气日期 public static void printSolarTerms(int year) { System.out.println(year + "年的二十四节气日期:"); for (String solarTerm : solarTerms) { System.out.printf("%s,%s%n", solarTerm, solarTermMap.get(solarTerm).withYear(year)); } } public static void main(String[] args) { printSolarTerms(2002); printSolarTerms(2003); printSolarTerms(2004); printSolarTerms(2005); printSolarTerms(2006); printSolarTerms(2007); printSolarTerms(2008); printSolarTerms(2009); printSolarTerms(2010); printSolarTerms(2011); printSolarTerms(2012); printSolarTerms(2013); printSolarTerms(2014); printSolarTerms(2015); printSolarTerms(2016); printSolarTerms(2017); printSolarTerms(2018); printSolarTerms(2019); printSolarTerms(2020); printSolarTerms(2021); printSolarTerms(2022); } } ``` 输出结果为: ``` 2002年的二十四节气日期: 立春,2002-02-04 雨水,2002-02-19 惊蛰,2002-03-06 春分,2002-03-21 清明,2002-04-05 谷雨,2002-04-20 立夏,2002-05-06 小满,2002-05-21 芒种,2002-06-06 夏至,2002-06-22 小暑,2002-07-08 大暑,2002-07-23 立秋,2002-08-08 处暑,2002-08-23 白露,2002-09-08 秋分,2002-09-23 寒露,2002-10-08 霜降,2002-10-23 立冬,2002-11-07 小雪,2002-11-22 大雪,2002-12-07 冬至,2002-12-22 小寒,2003-01-06 大寒,2003-01-21 2003年的二十四节气日期: 立春,2003-02-04 雨水,2003-02-19 惊蛰,2003-03-06 春分,2003-03-21 清明,2003-04-05 谷雨,2003-04-20 立夏,2003-05-06 小满,2003-05-21 芒种,2003-06-06 夏至,2003-06-22 小暑,2003-07-08 大暑,2003-07-23 立秋,2003-08-08 处暑,2003-08-23 白露,2003-09-08 秋分,2003-09-23 寒露,2003-10-08 霜降,2003-10-23 立冬,2003-11-07 小雪,2003-11-22 大雪,2003-12-07 冬至,2003-12-22 小寒,2004-01-06 大寒,2004-01-21 2004年的二十四节气日期: 立春,2004-02-04 雨水,2004-02-19 惊蛰,2004-03-05 春分,2004-03-20 清明,2004-04-04 谷雨,2004-04-19 立夏,2004-05-05 小满,2004-05-20 芒种,2004-06-05 夏至,2004-06-21 小暑,2004-07-07 大暑,2004-07-22 立秋,2004-08-07 处暑,2004-08-22 白露,2004-09-07 秋分,2004-09-22 寒露,2004-10-07 霜降,2004-10-22 立冬,2004-11-06 小雪,2004-11-21 大雪,2004-12-06 冬至,2004-12-21 小寒,2005-01-05 大寒,2005-01-20 2005年的二十四节气日期: 立春,2005-02-04 雨水,2005-02-19 惊蛰,2005-03-05 春分,2005-03-20 清明,2005-04-04 谷雨,2005-04-20 立夏,2005-05-05 小满,2005-05-21 芒种,2005-06-05 夏至,2005-06-21 小暑,2005-07-07 大暑,2005-07-22 立秋,2005-08-07 处暑,2005-08-23 白露,2005-09-07 秋分,2005-09-22 寒露,2005-10-08 霜降,2005-10-23 立冬,2005-11-07 小雪,2005-11-22 大雪,2005-12-07 冬至,2005-12-22 小寒,2006-01-06 大寒,2006-01-20 2006年的二十四节气日期: 立春,2006-02-04 雨水,2006-02-19 惊蛰,2006-03-05 春分,2006-03-20 清明,2006-04-04 谷雨,2006-04-20 立夏,2006-05-05 小满,2006-05-21 芒种,2006-06-06 夏至,2006-06-22 小暑,2006-07-07 大暑,2006-07-23 立秋,2006-08-08 处暑,2006-08-23 白露,2006-09-08 秋分,2006-09-23 寒露,2006-10-08 霜降,2006-10-23 立冬,2006-11-07 小雪,2006-11-22 大雪,2006-12-07 冬至,2006-12-22 小寒,2007-01-05 大寒,2007-01-20 2007年的二十四节气日期: 立春,2007-02-04 雨水,2007-02-19 惊蛰,2007-03-05 春分,2007-03-21 清明,2007-04-05 谷雨,2007-04-20 立夏,2007-05-05 小满,2007-05-21 芒种,2007-06-06 夏至,2007-06-22 小暑,2007-07-07 大暑,2007-07-23 立秋,2007-08-08 处暑,2007-08-23 白露,2007-09-08 秋分,2007-09-23 寒露,2007-10-08 霜降,2007-10-23 立冬,2007-11-07 小雪,2007-11-22 大雪,2007-12-07 冬至,2007-12-22 小寒,2008-01-06 大寒,2008-01-20 2008年的二十四节气日期: 立春,2008-02-04 雨水,2008-02-19 惊蛰,2008-03-05 春分,2008-03-20 清明,2008-04-04 谷雨,2008-04-19 立夏,2008-05-05 小满,2008-05-20 芒种,2008-06-05 夏至,2008-06-21 小暑,2008-07-07 大暑,2008-07-22 立秋,2008-08-07 处暑,2008-08-23 白露,2008-09-08 秋分,2008-09-23 寒露,2008-10-08 霜降,2008-10-23 立冬,2008-11-07 小雪,2008-11-22 大雪,2008-12-07 冬至,2008-12-22 小寒,2009-01-05 大寒,2009-01-20 2009年的二十四节气日期: 立春,2009-02-04 雨水,2009-02-19 惊蛰,2009-03-05 春分,2009-03-20 清明,2009-04-04 谷雨,2009-04-20 立夏,2009-05-05 小满,2009-05-21 芒种,2009-06-06 夏至,2009-06-22 小暑,2009-07-07 大暑,2009-07-23 立秋,2009-08-08 处暑,2009-08-23 白露,2009-09-08 秋分,2009-09-23 寒露,2009-10-08 霜降,2009-10-23 立冬,2009-11-07 小雪,2009-11-22 大雪,2009-12-07 冬至,2009-12-22 小寒,2010-01-06 大寒,2010-01-20 2010年的二十四节气日期: 立春,2010-02-04 雨水,2010-02-19 惊蛰,2010-03-05 春分,2010-03-21 清明,2010-04-05 谷雨,2010-04-20 立夏,2010-05-06 小满,2010-05-21 芒种,2010-06-06 夏至,2010-06-22 小暑,2010-07-07 大暑,2010-07-23 立秋,2010-08-08 处暑,2010-08-23 白露,2010-09-08 秋分,2010-09-23 寒露,2010-10-08 霜降,2010-10-23 立冬,2010-11-07 小雪,2010-11-22 大雪,2010-12-06 冬至,2010-12-21 小寒,2011-01-05 大寒,2011-01-20 201
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值