đź“–
Introduction to programming with Python
  • Introduction to programming with Python 3
  • Preface
    • Common misconceptions about learning to program
    • The Hard truth about learning to program
    • Personal qualities for success
  • 1 - The way of the program
    • Python Programming Language
    • The first program
    • What is debugging?
    • Glossary
    • Exercises
  • 2 - Variables, expressions and statements
    • Values, types and variables
    • Common Built-in data types
    • Expressions
    • Code Format
    • Debugging
    • Glossary
    • Exercises
  • 3 - Functions
    • Python "built-in" Functions
    • Math Functions
    • Composition
    • User Defined Functions
    • PEP 8 Recommendations
    • Debugging
    • Glossary
    • Exercises
  • 4 - Conditionals
    • Boolean expressions
    • Conditional statements
    • PEP 8 Recommendations
  • 5 - Iteration
    • The while statement
    • The for statement
    • break and continue statements
    • Nested Loops
    • PEP 8 Recommendations
    • Debugging
    • Glossary
    • Exercises
  • 6 - A short introduction to testing: Building Reliable Software
  • 7 - A deeper dive into Strings, Lists and Tuples
    • More on Strings
    • More on Lists
    • More on Tuples
    • Debugging
    • Glossary
    • Exercises
  • 8 - A deeper look at Functions in Python
    • Function Preconditions and Postconditions
    • Positional and Keywords arguments
    • Nested Functions
    • Scope of a variable
    • Recursion
    • Functions' side effects
    • Glossary
    • Exercises
  • 9 - Code Documentation
    • Basics of Commenting Code
    • Documenting Code via Python Docstring
  • 10 - Sets and dictionaries
    • Sets
    • Dictionaries
    • Which data structure should I use?
    • Debugging
    • Glossary
    • Exercises
  • 11 - File I/O
    • Read/Write to a file
    • File management
    • Debugging
    • Glossary
    • Exercises
  • 12 - Handling Errors and Exceptions
  • 13 - Writing modules
  • 14 - Classes
    • Classes and Objects
    • Classes and Functions
    • Classes and Methods
    • Pythonic Magic: Understanding and Implementing Dunder Methods
    • Glossary
    • Exercises
  • 15 - Python's Type Hinting
  • Acknowledgements
Powered by GitBook
On this page
  • The Essence of Software Testing
  • Test Driven Development
  • The Software Testing Lifecycle
  • The assert statement
  • A more advanced tool called unittest
  • Conclusion
Edit on GitHub

6 - A short introduction to testing: Building Reliable Software

PreviousExercisesNext7 - A deeper dive into Strings, Lists and Tuples

Last updated 1 year ago

The Essence of Software Testing

Software testing is the systematic process of evaluating a software application or system to identify defects, errors, or inconsistencies. It encompasses a wide range of activities aimed at assessing the software's behavior, performance, and compliance with specified requirements. Testing is not merely a phase; it's an ongoing discipline that runs parallel to development, guiding the software towards maturity and excellence.

Test Driven Development

One of the aspects of testing that is relevant for software design and implementation is the concept of test-driven development (TDD). TDD is a methodology that involves writing tests before writing the actual code. The tests define the expected behaviour and output of the code, and serve as a guide for the development process. The code is then written to pass the tests, and refactored as needed to improve its quality and readability. TDD helps to ensure that the code meets the requirements and specifications, and that it is easy to maintain and modify.

The Software Testing Lifecycle

Software testing is not a single, isolated task; it follows a structured lifecycle that aligns with the software development process. This lifecycle typically includes the following phases:

  1. Test Planning: Defining the testing objectives, scope, resources, and schedule.

  2. Test Design: Creating test cases, test scripts, and test data based on requirements and use cases.

  3. Test Execution: Running the tests, capturing results, and identifying defects.

  4. Defect Reporting: Documenting and reporting identified defects to the development team for resolution.

  5. Defect Retesting: Verifying that reported defects have been fixed correctly.

  6. Regression Testing: Ensuring that changes or enhancements do not introduce new defects.

  7. Test Closure: Summarizing testing activities, evaluating the exit criteria, and generating test reports.

The assert statement

A simple technique that a novice programmer can use for testing is the assert statement in Python. The assert statement checks if a given condition is true, and raises an AssertionError if it is false. The assert statement can be used to verify that the input, output, or intermediate values of a function or a program are correct, or that certain invariants or preconditions are satisfied. For example, the following code uses assert statements to test a function that calculates the factorial of a positive integer: In this example, the second line of code tests if the function’s precondition is true, that is the argument provided is positive.

def factorial(n):
    assert n >= 0, "n must be non-negative"
    if n == 0 or n == 1:
        return 1
    output = 1
    for i in range(2, n+1)
        output *= i
    return output

assert factorial(0) == 1, “factorial(0) must return 1”
assert factorial(1) == 1
assert factorial(2) == 2
assert factorial(3) == 6
assert factorial(4) == 24
assert factorial(5) == 120

The assert statements after the function definition check the post condition of the function, that is the returned value is the factorial of the argument.

The assert statements will raise an AssertionError if any of the conditions are false, indicating that there is an error in the code or the input. The assert statement can also take an optional second argument that provides a message to explain why the assertion failed.

A more advanced tool called unittest

The assert statement is a useful tool for testing, but it has some limitations. It can only check for simple conditions, and it does not provide a comprehensive report of the test results. It also stops the execution of the program when an assertion fails, which may not be desirable in some cases.

For more advanced testing, Python provides a module called unittest that supports automated testing with more features and flexibility. Unittest allows writing test cases as classes that inherit from unittest.TestCase, and using various methods to check for different types of assertions, such as assertTrue, assertFalse, assertEqual, assertNotEqual, assertRaises, etc. unittest also provides a test runner that can run all the test cases in a module or a package, and generate a detailed report of the test outcomes, such as passed, failed, skipped, or errored.

We will revisit this concept later, when we are familiar with implementing classes in Python.

Conclusion

In conclusion, testing is not an afterthought but a crucial aspect of programming. It ensures your software's reliability, saves time, and enhances your code's quality. Testing can also improve the design and implementation of the software, by making it clearer, more concise, and consistent.

Testing is a vital skill for any programmer or software engineer., and as a novice programmer, start with the simple yet effective assert statement. As you progress, consider exploring the power of unittest for more comprehensive testing.

Remember, in the world of coding, testing isn't just about finding errors; it's about building robust, dependable software.