Software projects perform several types of testing:
- Unit Testing tests individual components, such as classes and and functions.
- Integration Testing tests that components and services interact correctly.
- Functional or End-to-End Testing tests the entire application flow and behavior.
- Security Testing tests for secure flaws or vulnerabilities.
- Usability Testing to determine how well and easily users can use the software to perform what they want to do
- Acceptance Testing tests that application conforms to requirements and meets the users’ needs. Often required before delivering a software product.
Unit Testing
Unit testing tests individual classes, methods, and functions.
Presentation: Introduction to Unit Testing
Your development workflow should be:
- write some code
- write tests for what the code should do, based on the spec (not what you actually coded)
- run the tests
- analyze test failures and correct the code (or correct the tests)
- repeat
In Test Driven Development (TDD) you write the tests before you write the code. TDD often results in better tests and better code.
Unit Testing Benefits:
- avoids errors
- helps you stay focused on current work
- makes you think about what code should do, even in ‘edge’ cases
- avoid re-introducing previously fixed errors, called regression errors
- enables testing to be automated (unlike manual testing)
- gives you confidence to change the code
- tests are necessary before doing refactoring
How to design test cases?
- test behavior not just methods. One test may use several methods.
- test edge cases, failure cases, typical cases, extreme cases
- example tests for sqrt:
- edge case: sqrt(0), sqrt(1.0E-31)
- failure case: sqrt(-0.01)
- typical case:
sqrt(x) for x in [0.25, 0.5, 1, 1.5, 4.0, 26, (10000.5)**2]
- extreme case: sqrt(1.8E+308) -
1.8e+308
is the largest floating point value in Python
- things likely to go wrong, or where programmer may make a mistake
- “off by one” errors - requires some knowledge of the implementation
- empty input or empty lists
- using a file that doesn’t exist, is empty, or cannot be opened
Python Unit Testing
There are several good unit testing tools & frameworks for Python. The ones we will cover are:
- unittest the most commonly used test framework, included with Python
- PyTest a popular, light-weight testing framework. Results are easy to understand but test conditions are a bit limited.
- Doctest for test-by-example in code. Provides tests and documentation at the same time, but not usually a thorough test.
- Mock objects for programmable “fake” objects to isolate the target code from dependencies. You “mock” the dependencies to return known values. RealPython has good introduction.
Presentation: Python Unit Testing
Resources to learn unittest:
- Python unittest Docs are easy to read, many examples.
- Getting Started with Testing on RealPython introduces testing in general and examples of Python test tools
- Python Unittest Tutorial video on Youtube, 39 minutes.
Code Coverage
Code Coverage uses a tool to measure how much of your code is really being tested by unit tests.
- Easy to use while running your tests.
- Helps you find sections of code that you need to write better tests for.
To use code coverage on your own computer, use the coverage Python package:
coverage run -m unittest test_*.py
coverage report
# create a detailed report in HTML format
coverage html
# view the report in a web browser
firefox htmlcov/index.html
To run code coverage as part of automatic testing (C.I. or Github Actions) you run coverage
as above, then use CodeCov or Coveralls to process and display the .coverage data.
Java Unit Testing
Presentation: Unit Testing with JUnit may cover only JUnit 4.0
-
JUnit Home covers JUnit 4 & 5. Many examples.
-
JUnit Parameterized Tests parameterize unit tests instead of writing many test methods with nearly the same code
End-to-End Testing
Test the flow of the application “from start to finish”.
An E2E test typically covers one usage scenario, and you may want to test several scenarios. However, the goal is not comprehensive testing of everything.
What is E2E Testing? E2E Testing Framework with Examples is a short overview and describes some testing tools.
The Practical Testing Pyramid by Martin Fowler describes 3 levels of testing: unit test, integration test, and E2E test.
Verification and Validation
Verification
- Checking that a program performs according to the specifications (how it was specified & designed it to behave) [Kaner]
- Confirm that the software performs and conforms to its specification. [U.W.]
- “Are we building it right?” (informal interpretation)
Validation
- Checking that a program beaves according the the user or system requirements (what the customer said the program should do) [Kaner]
- Confirm that the software performs to the user’s satisfaction. Assure that the software meets the user’s (specified) needs. [U.W.]
- “Are we building the right thing?” (informal interpretation)
Note: definition 2 is the most descriptive. Definition 3 (informal) is not an acceptable answer on quiz or exam.
Two broad appoaches to perform V & V.
- Dynamic
- exercising (running) the software and oberving its behavior, i.e. testing
- Static
- inspection and analysis of the software representation (e.g. code to discover problems
- inspections, mathematical models and proofs
Security Testing
- Dynamic V & V
- penetration testing
- fuzzing
- Static V & V
- examine source code for common problems such as unchecked buffer writes, memory allocation/deallocation, trusting tainted data
- proofs related to privilege level
- Developers should care about both “building the thing right” and “building the right thing”
- Both Verification and Validation are important
- Both static and dynamic methods are necessary
- Verification is usually cheaper and easier than Validation
Testing Incomplete Software Under Development
Suppose you are writing module1
and want to test it,
but module1
depends on module2
that has not been written yet.
How can you test module1
?
- Write a stub for the interface to module2. These classes and methods don’t do anything, but enable you to run module1.
- Create Mock Objects to ‘stand in’ for module2 and simulate it’s behavior for your test cases. You can pre-program the values that module2 should return.
Who Performs Testing?
Developer
- + understands the software best
- - tests gently, maybe not trying to expose errors
- - driven by deadlines to finish code
- - may be “blind” to his own errors or misunderstanding
Tester
- + tries to break the system
- - must learn the software
- + driven by quality goal
- + not biased by developer’s perspective
Axioms and Guides for Testing
-
The probability of more, undedecting defects increases with the number of detected defects
-
Assign the best programmers to testing
-
Exhaustive testing is impossible
-
You cannot know when you have found the last bug – cannot guarantee software has zero defects
-
Testing takes more time than you have, even to test less than you would like
-
You will run out of time before you run out of test cases
- If that’s not true, you should look for more test cases
Web Testing
Presentation: Web Testing
There are special tools for testing web apps and web services. In this class we will use Selenium, and may cover the Robot Framework.
References
- Extensive List of Python Testing Tools on wiki.python.org includes mock objects, web testing, fuzz testing, source code checkers, code coverage, unit test, and acceptance/business logic testing tools.
- Testing Your Code good article introduces testing using unit test, py.test, Hypothesis, and mock.
- Getting Started with Testing on RealPython.
- Presention: Intro to Different Kinds of Testing, not relevant to this course
- ‘a’ tag without an href
- Another lame <a> tag to test your link scanner