简体   繁体   English

在 Python3 中使用单元测试进行单元测试

[英]Unit testing using unit test in Python3

I need to write test cases using unit test in Python for testing circle creation.我需要使用 Python 中的单元测试编写测试用例来测试圈子的创建。

  • Define a class Circle with method __init__ which initializes a circle with attribute radius , having following restrictions:使用方法__init__定义一个类Circle ,它使用属性radius初始化一个圆,具有以下限制:

    • radius must be numeric value, if not raise type error with error message "radius must be number". radius必须是数值,如果没有引发类型错误,错误消息“半径必须是数字”。

    • radius must be between 0 to 1000 inclusive on both sides, if not raise the value error with error message "radius must be between 0 and 1000 inclusive"两边的radius必须在 0 到 1000 之间(含),否则会引发错误消息“半径必须在 0 到 1000 之间”

    • Define a class method area and circumference which must return values rounded off to 2 decimals.定义一个类方法areacircumference ,它必须返回四舍五入到小数点后 2 位的值。

    Complete the definition of class TestingCircleCreation which tests the behavior of __init__ method as specification below.完成类TestingCircleCreation的定义,该类测试__init__方法的行为,如下所示。

  • Define the test method of test_creating_circle_with_numerical_radius which creates circle with radius 2.5 and check if radius matches to value 2.5定义test_creating_circle_with_numerical_radius的测试方法,它创建半径为 2.5 的圆并检查半径是否与值 2.5 匹配

  • Define the test method test_creating_circle_with_negative_radius which checks if value error exception is raised with the error message "radius must be between 0 and 1000 inclusive", while creating circle of radius 2.5.定义测试方法test_creating_circle_with_negative_radius检查是否引发值错误异常,并显示错误消息“半径必须介于 0 和 1000 之间”,同时创建半径为 2.5 的圆。

  • Define the test method test_creating_circle_with_greaterthan_radius which checks if ValueError exception is raised with error message "radius must be between 0 and 1000 inclusive", while creating circle of radius 1000.1.定义测试方法test_creating_circle_with_greaterthan_radius ,它检查是否引发ValueError异常,错误消息“半径必须介于 0 和 1000 之间”,同时创建半径为 1000.1 的圆。

  • Define the test method test_creating_circle_with_nonnumeric_radius , which checks if TypeError exception is raised with error message "radius must be number" while creating circle of radius 'hello'.定义测试方法test_creating_circle_with_nonnumeric_radius ,该方法在创建半径为“hello”的圆时检查是否TypeError异常并显示错误消息“radius must be number”。

I tried below but it is failing with error as我在下面尝试过,但由于错误而失败

Traceback (most recent call last):
  File "..\Playground\", line 86, in <module>
    pass_count = pass_count[0]
IndexError: list index out of range

The code:代码:

import inspect
import re
import unittest
import math

# Define below the class 'Circle' and it's methods with proper doctests.
class Circle:
    def __init__(self, radius):
        # Define the initialization method below
        try:
            if not isinstance(radius, (int, float)):
                raise TypeError 
            elif 1000 >=radius>=0:
                    self.radius=radius 
            else:
                raise ValueError        
        except ValueError:
            raise ValueError("radius must be between 0 and 1000 inclusive")
        except TypeError:
            raise TypeError("radius must be a number")
        
    def area(self):
        # Define the area functionality below
        y=math.pi*(self.radius**2)
        return round(y,2)
               
    def circumference(self):
        # Define the circumference functionality below
        x=math.pi*2*self.radius
        return round(x,2)
        
class TestCircleCreation(unittest.TestCase):
    def test_creating_circle_with_numeric_radius(self):
        # Define a circle 'c1' with radius 2.5 and check if 
        # the value of c1.radius equal to 2.5 or not
        c1=Circle(2.5)        
        self.assertEqual(c1.radius,2.5)

    def test_creating_circle_with_negative_radius(self):
        # Try Defining a circle 'c' with radius -2.5 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"
        c=Circle(-2.5)
        self.assertEqual(c.radius,-2.5)
        self.assertRaises(ValueError)      

    def test_creating_circle_with_greaterthan_radius(self):
        # Try Defining a circle 'c' with radius 1000.1 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"
        c=Circle(1000.1)        
        self.assertEqual(c.radius,1000.1)
        self.assertRaises(ValueError)        
        
    def test_creating_circle_with_nonnumeric_radius(self):
        # Try Defining a circle 'c' with radius 'hello' and see 
        # if it raises a TypeError with the message
        # "radius must be a number"
        c=Circle('hello')      
        self.assertEqual(c.radius,'hello')
        self.assertRaises(TypeError)        

if __name__ == '__main__':
    fptr = open('output.txt', 'w')
    
    runner = unittest.TextTestRunner(fptr)
    
    unittest.main(testRunner=runner, exit=False)
    
    fptr.close()
    
    with open('output.txt') as fp:
        output_lines = fp.readlines()
    
    pass_count = [ len(re.findall(r'\.', line)) for line in output_lines if line.startswith('.')
                     and line.endswith('.\n')]
    
    pass_count = pass_count[0]
    print(str(pass_count))
                       
    doc1 = inspect.getsource(TestCircleCreation.test_creating_circle_with_numeric_radius)
    doc2 = inspect.getsource(TestCircleCreation.test_creating_circle_with_negative_radius)
    doc3 = inspect.getsource(TestCircleCreation.test_creating_circle_with_greaterthan_radius)
    doc4 = inspect.getsource(TestCircleCreation.test_creating_circle_with_nonnumeric_radius)
    
    assert1_count = len(re.findall(r'assertEqual', doc1))
    print(str(assert1_count))
    
    assert1_count = len(re.findall(r'assertEqual', doc2))
    assert2_count = len(re.findall(r'assertRaises', doc2))
    print(str(assert1_count), str(assert2_count))
    
    assert1_count = len(re.findall(r'assertEqual', doc3))
    assert2_count = len(re.findall(r'assertRaises', doc3))
    print(str(assert1_count), str(assert2_count))
    
    assert1_count = len(re.findall(r'assertEqual', doc4))
    assert2_count = len(re.findall(r'assertRaises', doc4))
    print(str(assert1_count), str(assert2_count))
import inspect
import re
import unittest
import math

class Circle:    
    def __init__(self, radius):
        # Define the initialization method below
        self.radius=radius
        if not isinstance(self.radius,(int,float)):
            raise TypeError("radius must be a number")
        elif(self.radius>1000 or self.radius<0):
            raise ValueError("radius must be between 0 and 1000 inclusive")
        else:
            pass
    def area(self):
        # Define the area functionality below
        return math.pi*(self.radius**2)
    def circumference(self):
        return 2*math.pi*self.radius
        # Define the circumference functionality below

class TestCircleCreation(unittest.TestCase):
    def test_creating_circle_with_numeric_radius(self):
        # Define a circle 'c1' with radius 2.5 and check if 
        # the value of c1.radius equal to 2.5 or not
        c1=Circle(2.5)
        self.assertEqual(c1.radius,2.5)
       
    def test_creating_circle_with_negative_radius(self):
        # Try Defining a circle 'c' with radius -2.5 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"
        with self.assertRaises(ValueError) as e:
            c=Circle(-2.5)
        self.assertEqual(str(e.exception),"radius must be between 0 and 1000 inclusive")
        
    def test_creating_circle_with_greaterthan_radius(self):
        # Try Defining a circle 'c' with radius 1000.1 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"        
        with self.assertRaises(ValueError) as e:
            c=Circle(1000.1)
        self.assertEqual(str(e.exception),"radius must be between 0 and 1000 inclusive")
       
    def test_creating_circle_with_nonnumeric_radius(self):
        # Try Defining a circle 'c' with radius 'hello' and see 
        # if it raises a TypeError with the message
        # "radius must be a number"   
        with self.assertRaises(TypeError) as e:
            c=Circle("hello")
        self.assertEqual(str(e.exception),"radius must be a number")     

if __name__ == '__main__':
    fptr = open('output.txt', 'w')
    
    runner = unittest.TextTestRunner(fptr)
    
    unittest.main(testRunner=runner, exit=False)
    
    fptr.close()
    
    with open('output.txt') as fp:
        output_lines = fp.readlines()
    
    pass_count = [ len(re.findall(r'\.', line)) for line in output_lines if line.startswith('.')
                     and line.endswith('.\n')]
    
    pass_count = pass_count[0]          
    print(str(pass_count))
                       
    doc1 = inspect.getsource(TestCircleCreation.test_creating_circle_with_numeric_radius)
    doc2 = inspect.getsource(TestCircleCreation.test_creating_circle_with_negative_radius)
    doc3 = inspect.getsource(TestCircleCreation.test_creating_circle_with_greaterthan_radius)
    doc4 = inspect.getsource(TestCircleCreation.test_creating_circle_with_nonnumeric_radius)
    
    assert1_count = len(re.findall(r'assertEqual', doc1))
    print(str(assert1_count))
    
    assert1_count = len(re.findall(r'assertEqual', doc2))
    assert2_count = len(re.findall(r'assertRaises', doc2))
    print(str(assert1_count), str(assert2_count))
    
    assert1_count = len(re.findall(r'assertEqual', doc3))
    assert2_count = len(re.findall(r'assertRaises', doc3))
    print(str(assert1_count), str(assert2_count))
    
    assert1_count = len(re.findall(r'assertEqual', doc4))
    assert2_count = len(re.findall(r'assertRaises', doc4))
    print(str(assert1_count), str(assert2_count))
class Circle:
    def __init__(self, radius):
        # Define initialization method:
        self.radius = 0
        if not isinstance(radius,(int,float)):
            raise TypeError("radius must be a number")
        elif radius < 0 or radius > 1000:
            raise ValueError("radius must be between 0 and 1000 inclusive")
        else:
            self.radius = radius
        
    def area(self):
        # Define area functionality:
        return round(math.pi*(self.radius**2),2)
               
    def circumference(self):
        # Define circumference functionality:
        return round(2*math.pi*self.radius)

class TestCircleCreation(unittest.TestCase):
    def test_creating_circle_with_numeric_radius(self):
        # Define a circle 'c1' with radius 2.5, and check if 
        # the value of c1.radius is equal to 2.5 or not.
        c1 = Circle(2.5)
        self.assertEqual(c1.radius, 2.5)

    def test_creating_circle_with_negative_radius(self):
        # Define a circle 'c' with radius -2.5, and check 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive".
        with self.assertRaises(ValueError) as e:
            c = Circle(-2.5)
        self.assertEqual(str(e.exception),"radius must be between 0 and 1000 inclusive")
     
    def test_creating_circle_with_greaterthan_radius(self):
        # Define a circle 'c' with radius 1000.1, and check 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive".        
        with self.assertRaises(ValueError) as e:
            c = Circle(1000.1)
        self.assertEqual(str(e.exception),"radius must be between 0 and 1000 inclusive")      

    def test_creating_circle_with_nonnumeric_radius(self):
        # Define a circle 'c' with radius 'hello' and check 
        # if it raises a TypeError with the message
        # "radius must be a number".        
        with self.assertRaises(TypeError) as e:
            c = Circle("hello")
        self.assertEqual(str(e.exception), "radius must be a number")

I removed repeated self.assertEqual(c.radius,-2.5) assertions as they are already handled by another unit test ( test_creating_circle_with_numeric_radius(self) ), and causing your unittests to fail.我删除了重复的self.assertEqual(c.radius,-2.5)断言,因为它们已经由另一个单元测试( test_creating_circle_with_numeric_radius(self) )处理,并导致您的单元测试失败。 See here for example:例如,请参见此处:

    def test_creating_circle_with_negative_radius(self):
        c=Circle(-2.5)
        self.assertEqual(c.radius,-2.5) # Throwing ValueError
        self.assertRaises(ValueError)

In your code, the assertEquals(c.radius,-2.5) attempts to determine whether the value c.radius is equal to -2.5.在您的代码中, assertEquals(c.radius,-2.5)尝试确定值c.radius是否等于 -2.5。 This value is not set though because -2.5 is outside the acceptable range and a ValueError is thrown instead.但是未设置此值,因为-2.5超出了可接受的范围,而是抛出了 ValueError。 This prevents the self.assertRaises(ValueError) from being checked.这可以防止self.assertRaises(ValueError)被检查。 By removing assertEquals from the tests and leaving it as it's own independent test, self.assertRaises(ValueError) executes and allows you to see where your code does not adhere to the requirements.通过从测试中删除assertEquals并将其保留为自己的独立测试, self.assertRaises(ValueError)执行并允许您查看代码不符合要求的地方。

I've changed your tests to use context management to catch the exceptions thrown which has made the tests work correctly我已将您的测试更改为使用上下文管理来捕获引发的异常,从而使测试正常工作

class TestCircleCreation(unittest.TestCase):

    def test_creating_circle_with_numeric_radius(self):
        # Define a circle 'c1' with radius 2.5 and check if 
        # the value of c1.radius equal to 2.5 or not
        c1 = Circle(2.5)        
        self.assertEqual(c1.radius, 2.5)

    def test_creating_circle_with_negative_radius(self):
        # Try Defining a circle 'c' with radius -2.5 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"
        with self.assertRaises(ValueError) as E:
            c = Circle(-2.5)     

    def test_creating_circle_with_greaterthan_radius(self):
        # Try Defining a circle 'c' with radius 1000.1 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"
        with self.assertRaises(ValueError) as E:
            c = Circle(1000.1)        

    def test_creating_circle_with_nonnumeric_radius(self):
        # Try Defining a circle 'c' with radius 'hello' and see 
        # if it raises a TypeError with the message
        # "radius must be a number"
        with self.assertRaises(TypeError) as E:
            c = Circle('hello')        

Although this would also have worked:虽然这也有效:

class TestCircleCreation(unittest.TestCase):

    def test_creating_circle_with_numeric_radius(self):
        c1 = Circle(2.5)        
        self.assertEqual(c1.radius, 2.5)

    def test_creating_circle_with_negative_radius(self):
        self.assertRaises(ValueError, Circle, -2.5)

    def test_creating_circle_with_greaterthan_radius(self):
        self.assertRaises(ValueError, Circle, 1000.1)


    def test_creating_circle_with_nonnumeric_radius(self):
        self.assertRaises(TypeError, Circle, 'hello')

PS: I advise you to use with open when writing to the file, as you did when reading it back. PS:我建议您在写入文件时使用with open ,就像您在读回文件时一样。

    with open('output.txt', 'w') as fptr:
        runner = unittest.TextTestRunner(fptr)
        unittest.main(testRunner=runner, exit=False)

Your checks could be streamlined from您的支票可以简化为

        try:
            if not isinstance(radius, (int, float)):
                raise TypeError 
            elif 1000 >=radius>=0:
                    self.radius=radius 
            else:
                raise ValueError        
        except ValueError:
            raise ValueError("radius must be between 0 and 1000 inclusive")
        except TypeError:
            raise TypeError("radius must be a number")

to:到:

            if not isinstance(radius, (int, float)):
                raise TypeError("radius must be a number")

            if not 1000 >=radius>=0:
                raise ValueError("radius must be between 0 and 1000 inclusive")

            self.radius=radius 
import inspect
import re
import unittest
import math

# Define below the class 'Circle' and it's methods with proper doctests.
class Circle:
    def __init__(self, radius):
        # Define the initialization method below
        try:
            if not isinstance(radius, (int, float)):
                raise TypeError 
            elif 1000 >=radius>=0:
                    self.radius=radius 
            else:
                raise ValueError        
        except ValueError:
            raise ValueError("radius must be between 0 and 1000 inclusive")
        except TypeError:
            raise TypeError("radius must be a number")

    def area(self):
        # Define the area functionality below
        y=math.pi*(self.radius**2)
        return round(y,2)

    def circumference(self):
        # Define the circumference functionality below
        x=math.pi*2*self.radius
        return round(x,2)

class TestCircleCreation(unittest.TestCase):
    def test_creating_circle_with_numeric_radius(self):
        # Define a circle 'c1' with radius 2.5 and check if 
        # the value of c1.radius equal to 2.5 or not
        c1 = Circle(2.5)        
        self.assertEqual(c1.radius, 2.5)

    def test_creating_circle_with_negative_radius(self):
        # Try Defining a circle 'c' with radius -2.5 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"
        c1 = Circle(2.5)        
        self.assertEqual(c1.radius, 2.5)

        with self.assertRaises(ValueError) as E:
            c = Circle(-2.5)     

    def test_creating_circle_with_greaterthan_radius(self):
        # Try Defining a circle 'c' with radius 1000.1 and see 
        # if it raises a ValueError with the message
        # "radius must be between 0 and 1000 inclusive"

        c1 = Circle(2.5)        
        self.assertEqual(c1.radius, 2.5)
        with self.assertRaises(ValueError) as E:
            c = Circle(1000.1)        

    def test_creating_circle_with_nonnumeric_radius(self):
        # Try Defining a circle 'c' with radius 'hello' and see 
        # if it raises a TypeError with the message
        # "radius must be a number"

        c1 = Circle(2.5)        
        self.assertEqual(c1.radius, 2.5)

        with self.assertRaises(TypeError) as E:
            c = Circle('hello')        

if __name__ == '__main__':
    fptr = open('output.txt', 'w')

    runner = unittest.TextTestRunner(fptr)

    unittest.main(testRunner=runner, exit=False)

    fptr.close()

    with open('output.txt') as fp:
        output_lines = fp.readlines()

    pass_count = [ len(re.findall(r'\.', line)) for line in output_lines if line.startswith('.')
                     and line.endswith('.\n')]

    pass_count = pass_count[0]
    print(str(pass_count))

    doc1 = inspect.getsource(TestCircleCreation.test_creating_circle_with_numeric_radius)
    doc2 = inspect.getsource(TestCircleCreation.test_creating_circle_with_negative_radius)
    doc3 = inspect.getsource(TestCircleCreation.test_creating_circle_with_greaterthan_radius)
    doc4 = inspect.getsource(TestCircleCreation.test_creating_circle_with_nonnumeric_radius)

    assert1_count = len(re.findall(r'assertEqual', doc1))

    print(str(assert1_count))

    assert1_count = len(re.findall(r'assertEqual', doc2))
    assert2_count = len(re.findall(r'assertRaises', doc2))
    print(str(assert1_count), str(assert2_count))

    assert1_count = len(re.findall(r'assertEqual', doc3))
    assert2_count = len(re.findall(r'assertRaises', doc3))
    print(str(assert1_count), str(assert2_count))

    assert1_count = len(re.findall(r'assertEqual', doc4))
    assert2_count = len(re.findall(r'assertRaises', doc4))
    print(str(assert1_count), str(assert2_count))

4 1 1 1,11,11 1 meant?? 4 1 1 1,11,11 1 是什么意思?? in code we are not passing anything like this.在代码中,我们没有传递这样的东西。 can you please explain me?你能解释一下吗? 4 1 0 1 0 1 0 1 meant? 4 1 0 1 0 1 0 1 是什么意思?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM