• 单元测试框架Unittest


    Unittest官方 4个重要概念:

    Test fixture(测试固件):初始化、清除

    Test case(测试用例),test suite(测试套件),test runner(测试运行器)

    两种单元测试加载方法:

    1.unittest.main()

    2.将所有test case 添加到test suit中,然后一次性加载

    知识点:

    1.测试类要继承unittest.TestCase类

    2.每个用例方法 test开头(self)

    3.setUp和tearDown方法在每个用例执行前后都会执行

    4.unittest.main()执行同一模块内unittest子类所有方法

    实例

    被测试模块 Calc.py 

    后续部分用例会引用此模块

     1 # coding=utf-8
     2 class Calc(object):
     3     def add(self, x, y, *d):
     4         # 加法计算
     5         result = x + y
     6         for i in d:
     7             result += i
     8         return result
     9 
    10     def sub(self, x, y, *d):
    11         # 减法计算
    12         result = x - y
    13         for i in d:
    14             result -= i
    15         return result
    16 
    17     @classmethod
    18     def mul(cls, x, y, *d):
    19         # 乘法计算
    20         result = x * y
    21         for i in d:
    22             result *= i
    23         return result
    24 
    25     @staticmethod
    26     def div(x, y, *d):
    27         # 除法计算
    28         if y != 0:
    29             result = x / y
    30         else:
    31             return -1
    32         for i in d:
    33             if i != 0:
    34                 result /= i
    35             else:
    36                 return -1
    37         return result

    例子1 用例初始化清除setUp、tearDown

     1 #encoding=utf-8
     2 import unittest
     3 import random
     4 class TestSequenceFunctions(unittest.TestCase):
     5     def setUp(self):
     6         # 初始化一个递增序列
     7         self.seq = range(10)
     8         print "setup completed!"
     9 
    10     def test_run(self):
    11         # 从序列seq中随机选取一个元素
    12         element = random.choice(self.seq)
    13         # 验证随机元素确实属于列表中
    14         self.assertTrue(element in self.seq)
    15 
    16     def test_sth(self):
    17         assert 1==1
    18 
    19     def tearDown(self):
    20         print "tearDown completed"
    21 
    22 class TestDictValueFormatFunctions(unittest.TestCase):
    23     def setUp(self):
    24         self.seq = range(10)
    25 
    26     def test_shuffle(self):
    27         # 随机打乱原seq的顺序
    28         random.shuffle(self.seq)
    29         self.seq.sort()
    30         self.assertEqual(self.seq, range(10))
    31         # 验证执行函数时抛出了TypeError异常
    32         self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
    33 
    34 if __name__ == '__main__':
    35 unittest.main()

    例子2 类初始化清除setUpClass(cls)、tearDownClass(cls)

    类里所有用例执行前后仅执行一次

     1 #encoding=utf-8
     2 import unittest
     3 
     4 # 被测试类
     5 class myclass(object):
     6     @classmethod
     7     def sum(self, a, b):
     8         return a + b #将两个传入参数进行相加操作
     9 
    10     @classmethod
    11     def sub(self, a, b):
    12         return a - b #将两个传入参数进行相减操作
    13 
    14 
    15 class mytest(unittest.TestCase):
    16     @classmethod
    17     def setUpClass(cls):
    18         "初始化类固件"
    19         print "----setUpClass"
    20 
    21     @classmethod
    22     def tearDownClass(cls):
    23         "重构类固件"
    24         print "----tearDownClass"
    25 
    26     # 初始化工作
    27     def setUp(self):
    28         self.a = 3
    29         self.b = 1
    30         print "--setUp"
    31 
    32     # 退出清理工作
    33     def tearDown(self):
    34         print "--tearDown"
    35 
    36     # 具体的测试用例,一定要以test开头
    37     def testsum(self):
    38         # 断言两数之和的结果是否是4
    39         self.assertEqual(myclass.sum(self.a, self.b), 4, 'test sum fail')
    40 
    41     def testsub(self):
    42         # 断言两数之差的结果是否是2
    43         self.assertEqual(myclass.sub(self.a, self.b), 2, 'test sub fail')
    44 
    45 
    46 if __name__ == '__main__':
    47 unittest.main() # 启动单元测试

    例子3  按特定顺序执行用例

    unittest框架用例执行顺序是按照用例名字符的ASCII码顺序

    用例数小于10:可将用例名命名为test加0-9, 按数字由小到大顺序执行

    用例数大于10:可将用例名字首字母开始命名 a-Z按顺序执行,如第一字母相同,则第二字母再按a-Z顺序排序,以此类推

    suit.addTest(class(‘testcase’)) 按此方式添加的用例会按添加顺序执行

    此代码需要文本开头的被测试模块Calc.py

     1 #encoding=utf-8
     2 import unittest
     3 from Calc import Calc
     4 
     5 class MyTest(unittest.TestCase):
     6 
     7     @classmethod
     8     def setUpClass(self):
     9         print u"单元测试前,创建Calc类的实例"
    10         self.c = Calc()
    11 
    12     # 具体的测试用例,一定要以test开头,执行顺序按照字母顺序开头
    13     def test_0add(self):
    14         print "run add()"
    15         self.assertEqual(self.c.add(1, 2, 12), 15, 'test add fail')
    16 
    17     def test_1sub(self):
    18         print "run sub()"
    19         self.assertEqual(self.c.sub(2, 1, 3), -2, 'test sub fail')
    20 
    21     def test_2mul(self):
    22         print "run mul()"
    23         self.assertEqual(Calc.mul(2, 3, 5), 30, 'test mul fail')
    24 
    25     def test_3div(self):
    26         print "run div()"
    27         self.assertEqual(Calc.div(8, 2, 4), 1, 'test div fail')
    28 
    29 if __name__ == '__main__':
    30 unittest.main()# 启动单元测试
    31 
    32 
    33 if __name__ == '__main__':
    34 suite = unittest.TestSuite()
    35 suite.addTest(MyTest(‘test_2mu’))
    36 suite.addTest(MyTest(‘test_1sub’))
    37 runner = unittest.TextTestRunner()
    38 runner.run(suite)

    例子4 忽略测试方法,不想执行的用例,可跳过

    unittet可以分无条件忽略和有条件忽略,通过装饰器实现

    跳过用例时打印括号内后面参数的内容(跳过原因)

    @unittest.skip(reason) 装饰器:无条件跳过装饰的测试,并说明跳过测试的原因。

    @unittest.skipIf(a > 5, "condition is not satisfied!") 条件为真时,跳过装饰的测试,并说明跳过测试的原因。

    @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")条件为假时,跳过装饰的测试,并说明跳过测试的原因。

    @unittest.expectedFailure(): expectedFailure()测试标记为失败。

     1 # coding=utf-8
     2 import random
     3 import unittest    
     4 import sys
     5 
     6 class TestSequenceFunctions(unittest.TestCase):
     7     a = 1
     8 
     9     def setUp(self):
    10         self.seq = list(range(10))
    11 
    12     @unittest.skip("skipping") # 无条件忽略该测试方法
    13     def test_shuffle(self):
    14         random.shuffle(self.seq)
    15         self.seq.sort()
    16         self.assertEqual(self.seq, list(range(10)))
    17         self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
    18 
    19     # 如果变量a > 5,则忽略该测试方法
    20     @unittest.skipIf(a > 5, "condition is not satisfied!")
    21     def test_choice(self):
    22         element = random.choice(self.seq)
    23         self.assertTrue(element in self.seq)
    24 
    25     # 除非执行测试用例的平台是Linux平台,否则忽略该测试方法是windows
    26     @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
    27     def test_sample(self):
    28         with self.assertRaises(ValueError):
    29             random.sample(self.seq, 20)
    30         for element in random.sample(self.seq, 5):
    31             self.assertTrue(element in self.seq)
    32 
    33 
    34 if __name__ == '__main__':
    35     # unittest.main()
    36     Case = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
    37     suite = unittest.TestSuite(Case)
    38 unittest.TextTestRunner(verbosity = 2).run(suite)

    例子5 测试集合,批量执行测试用例

    根据给定的测试类,获取其中的所有以“test”开头的测试方法,并返回一个测试套件

    suite1=unittest.TestLoader().loadTestsFromTestCase(Class)

    将多个测试类加载到测试套件中

    suite = unittest.TestSuite([suite2, suite1,suite3]) 

    通过调整suit2和suite1的顺序,可以设定执行顺序

    设置verbosity = 2,可以打印出更详细的执行信息

    unittest.TextTestRunner(verbosity = 2).run(suite)

    方式1:模块中直接调用unittest.main() 

    此代码需要文本开头的被测试模块Calc.py

    此代码模块名:TestCalc.py(下一段代码会用到)

     1 #encoding=utf-8
     2 import unittest
     3 import random
     4 from Calc import Calc
     5 
     6 class TestCalcFunctions(unittest.TestCase):
     7     def setUp(self):
     8         self.c=Calc()
     9         print "setup completed!"
    10 
    11     def test_sum(self):
    12         self.assertTrue(self.c.add(1,2,3,4)==10)
    13         
    14     def test_sub(self):
    15         self.assertTrue(self.c.sub(100,20,30,40)==10)
    16 
    17     def test_mul(self):
    18         self.assertTrue(self.c.mul(1,2,3,40)==240)
    19 
    20     def test_div(self):
    21         self.assertTrue(self.c.div(100,10,2)==5)
    22 
    23     def tearDown(self):
    24         
    25         print "test completed!"
    26 
    27         
    28     def tearDown(self):
    29         print "tearDown completed"
    30 
    31 if __name__ == '__main__':
    32 unittest.main()

    方式2:测试用例类加载到一个套件中

     1 #encoding=utf-8
     2 import random
     3 import unittest
     4 from TestCalc import TestCalcFunctions
     5 class TestSequenceFunctions(unittest.TestCase):
     6     def setUp(self):
     7         self.seq = range(10)
     8 
     9     def tearDown(self):
    10         pass
    11 
    12     def test_choice(self):
    13         # 从序列seq中随机选取一个元素
    14         element = random.choice(self.seq)
    15         # 验证随机元素确实属于列表中
    16         self.assertTrue(element in self.seq)
    17 
    18     def test_sample(self):
    19         # 验证执行的语句是否抛出了异常
    20         with self.assertRaises(ValueError):
    21             random.sample(self.seq, 20)
    22         for element in random.sample(self.seq, 5):
    23             self.assertTrue(element in self.seq)
    24 
    25 
    26 class TestDictValueFormatFunctions(unittest.TestCase):
    27     def setUp(self):
    28         self.seq = range(10)
    29 
    30     def tearDown(self):
    31         pass
    32 
    33     def test_shuffle(self):
    34         # 随机打乱原seq的顺序
    35         random.shuffle(self.seq)
    36         self.seq.sort()
    37         self.assertEqual(self.seq, range(10))
    38         # 验证执行函数时抛出了TypeError异常
    39         self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
    40 
    41 if __name__ == '__main__':
    42     # 根据给定的测试类,获取其中的所有以“test”开头的测试方法,并返回一个测试套件
    43     suite1=unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
    44     suite2= unittest.TestLoader().loadTestsFromTestCase(TestDictValueFormatFunctions)
    45     suite3 = unittest.TestLoader().loadTestsFromTestCase(TestCalcFunctions)
    46     # 将多个测试类加载到测试套件中
    47     suite = unittest.TestSuite([suite2, suite1,suite3])  #通过调整suit2和suite1的顺序,可以设定执行顺序
    48     # 设置verbosity = 2,可以打印出更详细的执行信息
    49     unittest.TextTestRunner(verbosity = 2).run(suite)

    例子6 断言

    self.assertRaises(TypeError,callable,argvs)验证执行函数时抛出了TypeError异常

    执行用例时出现异常,该用例会打印一个E;断言失败则会打印F,代表Fail

      1 #encoding=utf-8
      2 import unittest
      3 import random
      4 
      5 # 被测试类
      6 class MyClass(object):
      7     @classmethod
      8     def sum(self, a, b):
      9         return a + b
     10 
     11     @classmethod
     12     def div(self, a, b):
     13         return a / b
     14 
     15     @classmethod
     16     def retrun_None(self):
     17         return None
     18 
     19 # 单元测试类
     20 class MyTest(unittest.TestCase):
     21 
     22     # assertEqual()方法实例
     23     def test_assertEqual(self):
     24         # 断言两数之和的结果
     25         try:
     26             a, b = 1, 2
     27             sum = 3
     28             self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
     29         except AssertionError, e:
     30             print e
     31 
     32     # assertNotEqual()方法实例
     33     def test_assertNotEqual(self):
     34         # 断言两数之差的结果
     35         try:
     36             a, b = 5, 2
     37             res = 1
     38             self.assertNotEqual(a - b, res, '断言失败,%s - %s != %s' %(a, b, res))
     39         except AssertionError, e:
     40             print e
     41 
     42     # assertTrue()方法实例
     43     def test_assertTrue(self):
     44         # 断言表达式的为真
     45         try:
     46             self.assertTrue(1 == 1, "表达式为假")
     47         except AssertionError, e:
     48             print e
     49 
     50     # assertFalse()方法实例
     51     def test_assertFalse(self):
     52         # 断言表达式为假
     53         try:
     54             self.assertFalse(3 == 2, "表达式为真")
     55         except AssertionError, e:
     56             print e
     57 
     58     # assertIs()方法实例
     59     def test_assertIs(self):
     60         # 断言两变量类型属于同一对象
     61         try:
     62             a = 12
     63             b = a
     64             self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
     65         except AssertionError, e:
     66             print e
     67 
     68     # test_assertIsNot()方法实例
     69     def test_assertIsNot(self):
     70         # 断言两变量类型不属于同一对象
     71         try:
     72             a = 12
     73             b = "test"
     74             self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
     75         except AssertionError, e:
     76             print e
     77 
     78     # assertIsNone()方法实例
     79     def test_assertIsNone(self):
     80         # 断言表达式结果为None
     81         try:
     82             result = MyClass.retrun_None()
     83             self.assertIsNone(result, "not is None")
     84         except AssertionError, e:
     85             print e
     86 
     87     # assertIsNotNone()方法实例
     88     def test_assertIsNotNone(self):
     89         # 断言表达式结果不为None
     90         try:
     91             result = MyClass.sum(2, 5)
     92             self.assertIsNotNone(result, "is None")
     93         except AssertionError, e:
     94             print e
     95 
     96     # assertIn()方法实例
     97     def test_assertIn(self):
     98         # 断言对象A是否包含在对象B中
     99         try:
    100             strA = "this is a test"
    101             strB = "is"
    102             self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
    103         except AssertionError, e:
    104             print e
    105 
    106     # assertNotIn()方法实例
    107     def test_assertNotIn(self):
    108         # 断言对象A不包含在对象B中
    109         try:
    110             strA = "this is a test"
    111             strB = "Selenium"
    112             self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
    113         except AssertionError, e:
    114             print e
    115 
    116     # assertIsInstance()方法实例
    117     def test_assertIsInstance(self):
    118         # 测试对象A的类型是否值指定的类型
    119         try:
    120             x = MyClass
    121             y = object
    122             self.assertIsInstance(x, y, "%s的类型不是%s".decode("utf-8") %(x, y))
    123         except AssertionError, e:
    124             print e
    125 
    126     # assertNotIsInstance()方法实例
    127     def test_assertNotIsInstance(self):
    128         # 测试对象A的类型不是指定的类型
    129         try:
    130             a = 123
    131             b = str
    132             self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
    133         except AssertionError, e:
    134             print e
    135 
    136     # assertRaises()方法实例
    137     def test_assertRaises(self):
    138         # 测试抛出的指定的异常类型
    139         # assertRaises(exception)
    140         with self.assertRaises(ValueError) as cm:
    141             random.sample([1,2,3,4,5], "j")
    142         # 打印详细的异常信息
    143         #print "===", cm.exception
    144 
    145         # assertRaises(exception, callable, *args, **kwds)
    146         try:
    147             self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
    148         except ZeroDivisionError, e:
    149             print e
    150 
    151     # assertRaisesRegexp()方法实例
    152     def test_assertRaisesRegexp(self):
    153         # 测试抛出的指定异常类型,并用正则表达式具体验证
    154         # assertRaisesRegexp(exception, regexp)
    155         with self.assertRaisesRegexp(ValueError, 'literal') as ar:
    156             int("xyz")
    157         # 打印详细的异常信息
    158         #print ar.exception
    159         # 打印正则表达式
    160         #print "re:",ar.expected_regexp
    161 
    162         # assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
    163         try:
    164             self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
    165         except AssertionError, e:
    166             print e
    167 
    168 
    169 if __name__ == '__main__':
    170     # 执行单元测试
    171 unittest.main()

    例子7 生成报告

    HTMLTestRunner.py和执行程序文件放置同一目录

     

     1 # coding=utf-8
     2 import unittest
     3 import HTMLTestRunner
     4 import math
     5 
     6 class Calc(object):
     7 
     8     def add(self, x, y, *d):
     9         # 加法计算
    10         result = x + y
    11         for i in d:
    12             result += i
    13         return result
    14 
    15     def sub(self, x, y, *d):
    16         # 减法计算
    17         result = x - y
    18         for i in d:
    19             result -= i
    20         return result
    21 
    22 class SuiteTestCalc(unittest.TestCase):
    23     def setUp(self):
    24         self.c = Calc()
    25 
    26     @unittest.skip("skipping")
    27     def test_Sub(self):
    28         print "sub"
    29         self.assertEqual(self.c.sub(100, 34, 6), 61, u'求差结果错误!')
    30 
    31     def testAdd(self):
    32         print "add"
    33         self.assertEqual(self.c.add(1, 32, 56), 89, u'求和结果错误!')
    34 
    35 
    36 class SuiteTestPow(unittest.TestCase):
    37     def setUp(self):
    38         self.seq = range(10)
    39 
    40     # @unittest.skipIf()
    41     def test_Pow(self):
    42         print "Pow"
    43         self.assertEqual(pow(6, 3), 2161, u'求幂结果错误!')
    44 
    45     def test_hasattr(self):
    46         print "hasattr"
    47 # 检测math模块是否存在pow属性
    48         self.assertTrue(hasattr(math, 'pow1'), u"检测的属性不存在!")
    49 
    50 if __name__ == "__main__":
    51     suite1 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestCalc)
    52     suite2 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestPow)
    53     suite = unittest.TestSuite([suite1, suite2])
    54     #unittest.TextTestRunner(verbosity=2).run(suite)
    55     filename = "test.html"  # 定义个报告存放路径,支持相对路径。
    56     # 以二进制方式打开文件,准备写
    57     fp = file(filename, 'wb')
    58     # 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
    59     runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
    60         title = 'Report_title', description = 'Report_description')
    61     # 运行测试集合
    62     runner.run(suite)

    例子8 批量执行多个模块生成报告

    1程序文件模式

    即将测试发现代码编写在测试脚本中,然后直接执行脚本文件即可,具体由

    TestLoader().discover(dir)实现,dir为被测试模块目录

    模块名需test开头,测试方法也要test开头,类名不需要test开头

     1 #coding=utf-8
     2 import unittest
     3 import HTMLTestRunner
     4  
     5 if __name__ == '__main__' :
     6     # 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
     7     testSuite = unittest.TestLoader().discover('.')
     8     filename = "test.html"  # 定义个报告存放路径,支持相对路径。
     9     # 以二进制方式打开文件,准备写
    10     fp = file(filename, 'wb')
    11     # 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
    12     runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
    13         title = 'Report_title', description = 'Report_description')
    14     # 运行测试集合
    15 runner.run(testSuite)

    2命令行模式

    unittest支持简单的test discovery. 命令行传入discovery后,框架会自动在当前目录搜索要测试的案例并执行.搜索目录必须是包或者模块.基本使用如下:

    python -m unittest discover

    子选项如下:
    -v, –verbose

    python -m unittest discover -v
    输出信息的详细级别

    -s, –start-directory directory

    python -m unittest discover -s other_dir
    开始搜索目录 (默认为当前目录)

    -p, –pattern pattern

    python -m unittest discover -p ‘YW*.py’
    匹配的文件名 (默认为test*.py)

    -t, –top-level-directory directory

    python -m unittest discover -t g:
    搜索的顶层目录 (默认为start directory)

     

    例子9 webdriver和unittest结合

     1 #encoding=utf-8
     2 import unittest
     3 from selenium import webdriver
     4 import time
     5 
     6 class WebTest(unittest.TestCase):
     7     def setUp(self):
     8         # 启动Firefox浏览器
     9         self.driver=webdriver.Firefox(executable_path = "d:\drivergeckodriver")
    10 
    11     def testSoGou(self):
    12         # 访问搜狗首页
    13         self.driver.get("http://sogou.com")
    14         # 清空搜索输入框默认内容
    15         self.driver.find_element_by_id("query").clear()
    16         # 在搜索输入框中输入“自动化测试”
    17         self.driver.find_element_by_id("query").send_keys(u"自动化测试")
    18         # 单击“搜索”按钮
    19         self.driver.find_element_by_id("stb").click()
    20         # 等待3秒
    21         time.sleep(3)
    22         assert u"web自动化" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk")
    23 
    24 
    25     def testBing(self):
    26         # 访问搜狗首页
    27         self.driver.get("http://cn.bing.com")
    28         # 清空搜索输入框默认内容
    29         self.driver.find_element_by_id("sb_form_q").clear()
    30         # 在搜索输入框中输入“自动化测试”
    31         self.driver.find_element_by_id("sb_form_q").send_keys(u"自动化测试")
    32         # 单击“搜索”按钮
    33         self.driver.find_element_by_id("sb_form_go").click()
    34         # 等待3秒
    35         time.sleep(3)
    36         assert u"web自动化" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk")
    37 
    38 
    39     def tearDown(self):
    40         # 退出浏览器
    41         self.driver.quit()
    42 
    43 if __name__ == '__main__':
    44 unittest.main()

    例子10 补充:命令行模式执行测试用例

    1.     运行整个测试模块

    python -m unittest test_module1 test_module2……

    2.     执行测试模块中某个测试类

    python -m unittest test_module.TestClass

    3.     执行测试模块中某个测试类下的测试方法

    python -m unittest test_module.TestClass.test_method

    练习

    写一个读文件的类,里面有个方法可以读取文件的全部内容。

    写个单元测试,断言文件中包含关键字"well done!"

     1 #被测试模块:readcont.py
     2 
     3 #coding=utf-8
     4 import unittest
     5 import os.path
     6 
     7 class TestReadContent():
     8     @staticmethod
     9     def read_content(filepath):
    10         if os.path.exists(filepath):
    11             with open(filepath) as fp:
    12                 return fp.read()
    13         else:
    14             return ''
    15 if __name__=='__main__':
    16     fcon = TestReadContent.read_content('g:/a.txt')
    17     print fcon
    18 
    19 #单元测试模块:
    20 
    21 #coding= utf-8
    22 import unittest
    23 from readcont import TestReadContent
    24 
    25 class TestRead(unittest.TestCase):
    26     def test_run(self):
    27         content = TestReadContent.read_content('g:/a.txt')
    28         self.assertTrue('well done!' in content )
    29 
    30 if __name__=='__main__':
    31 unittest.main()
  • 相关阅读:
    允许电脑被远程连接
    电脑更改用户密码
    HTML ------- 对文本进行操作的元素
    货币的发展
    SQL-----数据库三种删除方式详解
    HTML -------- 标签、元素、属性,
    HTML -------- 简介
    SQL --------------- HAVING 子句
    SQL --------------- GROUP BY 函数
    Shell编程——运算符
  • 原文地址:https://www.cnblogs.com/zeke-python-road/p/9153320.html
Copyright © 2020-2023  润新知