Skip to content

Latest commit

 

History

History
183 lines (120 loc) · 3.8 KB

File metadata and controls

183 lines (120 loc) · 3.8 KB

Unit Testing in Python

Let's learn about Pytest and Unittest



Before getting started


What is Unit Testing?

: A repetitive activity of verifying that individual code units within a module or application work as expected


Why Unit Testing is Necessary

  • Helps you think about how to write code
  • Helps determine whether implementation choices are appropriate when deciding what needs to be done
  • Allows you to find bugs quickly and fix them easily
  • Can improve code quality
  • Simplifies integration and improves design
  • Streamlines the debugging process

Python test frameworks

  • Unittest
  • Doctest
  • Pytest


What is Unittest?

  • The default test framework that comes with the Python standard library
  • Not as broad in scope as other third-party test frameworks
    • Provides only the functionality needed to write unit tests suitable for most projects
  • Was influenced by Java's JUnit testing framework
    • Therefore, you cannot write test functions without creating a class for testing

Unittest example

import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

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

Unittest Fixtures

: Refers to the process of setup before a test is run or clean-up after it finishes

  • setUp()

    • A method called before each test method is invoked
  • setUpClass()

    • A method called only once when the class starts

    • The method must have the @classmethod decorator and cls must be passed as an argument

    • ex)

      @classmethod
      def setUpClass(cls):
          ...
  • tearDown()

    • A method called after each test finishes
    • Runs even if an exception occurs during the test
    • However, it is only called if the setUp() method was successful
  • tearDownClass()

    • A method called only once after the class finishes

    • Similarly, the method must have the @classmethod decorator and cls must be passed as an argument

    • ex)

      @classmethod
      def tearDownClass(cls):
          ...



What is Pytest?

  • Unlike Unittest, Pytest allows you to create test methods as functions that follow specific naming conventions in a module, rather than requiring a Class

Pytest Fixtures

  • Provides fixtures in a unique way unlike other testing frameworks

  • Makes it easy to identify which test uses which fixture

  • ex)

    from handler import handler
    
    @pytest.fixture()
    def load_file():
        file = None
        try:
            file = open("sample_file.json", "r")
            content = eval(file.read())
        finally:
            if file:
                file.close()
    
        return content
    
    def test_handler(load_file):
       handler(load_file)

XFail

  • Allows you to indicate that a test function is expected to fail

    • Can be used when writing tests that are supposed to fail
      • ex) Test code to prevent incorrect data types
  • ex)

    from handler import handler
    
    @pytest.fixture()
    def load_wrong_format_file():
        file = None
        try:
            file = open("sample_file.txt", "r")
            content = eval(file.read())
        finally:
            if file:
                file.close()
    
        return content
    
    @pytest.mark.xfail
    def test_handler_with_wrong_format_file(self, load_wrong_format_file):
       handler(load_wrong_format_file)