This document gives an overview of basic testing concepts, including:
- Test types
- Hermetic builds (what environment provisioning is for)
- backoff/retry policies (for async operations)
Types of tests
This guide covers three common types of tests that you can use to ensure that your code works correctly:
- Unit tests
- Integration tests
- System tests
In general, more thorough tests take more time to complete. This document discusses these test types in detail, and gives some tips on how to strike a balance between speed and thoroughness.
Unit tests are narrowly-scoped tests for small, specific parts of your code. These tests can quickly verify assumptions made during the development process, such as handling edge cases and input validation.
By design, unit tests do not test integration with any external dependencies, such as Cloud Functions itself or other Google Cloud components. You can use your mocking framework to create mock versions of external dependencies.
For HTTP functions, tests should mock the wrapping HTTP framework. Confirm the function's behavior by combining testing and mocking frameworks and comparing your function's results to expected values.
Integration tests validate interaction between parts of your code, and typically take a moderate amount of time to complete. For example, in Cloud Functions, integration tests can be used to test a function's usage of other Google Cloud services such as Datastore or Cloud Vision.
The primary difference between unit tests and integration tests for Cloud Functions is that integration tests involve less mocking than unit tests. Integration tests should trigger and respond to actual Cloud events such as HTTP requests, Pub/Sub messages, or Storage object changes.
You can run integration tests locally using a shim.
Some asynchronous operations may require periodic polling. We recommend using the truncated exponential backoff polling strategy, as it effectively minimizes both the underlying operation's latency as well as the polling frequency required. Truncated exponential backoff is a standard error handling strategy for network applications in which a client periodically retries a failed request with increasing delays between requests.
System tests are more complex tests that validate the behavior of your Cloud Function across multiple Google Cloud components in an isolated test environment.
Deploy your Cloud Function to a test environment and test its functionality by triggering the appropriate events. Validate your function by reading the logs or checking for the desired behavior.
Best practices for testing environments
First, be sure to isolate your development, testing, and production environments. In order to guarantee hermetic builds, we recommend programmatically provisioning test resources with their own unique Google Cloud projects and/or resource names.
Second, we recommend assigning resources used by system tests globally unique names to prevent concurrent tests from interfering with each other. You can do this by programmatically creating and deleting the required resources before and after each test run.
Finally, we recommend keeping configuration values separate from your codebase. Non-secret values can be stored as environment variables, while secret values (such as database passwords and API keys) should be stored using Secret Manager.