I’m using pytest for my test execution, and I’m seeing a peculiar issue – when I run the tests locally, all the variables I pass in are sent to the test. When I run the same test on google cloud build, the same variables are printed as the $names of the variables instead. I see that I could be wrong about the way I’m currently using the scope for my fixtures but I am not able to pinpoint it. Can someone help me to figure out where am I making a mistake?
For example, here is the local test execution result:
--------------------------------------------------------------------------------------- live log setup ---------------------------------------------------------------------------------------
May 16 2024 07:33PM [INFO] my-user-id: valid_user_id (test_code.py:25)
May 16 2024 07:33PM [INFO] my-client-id: valid_client_id (test_code.py:26)
May 16 2024 07:33PM [INFO] os.environ.my-user-id: valid_user_id (test_code.py:27)
May 16 2024 07:33PM [INFO] os.environ.my-client-id: valid_client_id (test_code.py:28)
May 16 2024 07:33PM [INFO] request_params.MY_USER_ID: valid_user_id (test_code.py:29)
May 16 2024 07:33PM [INFO] request_params.MY_CLIENT_ID: valid_client_id (test_code.py:30)
--------------------------------------------------------------------------------------- live log call ----------------------------------------------------------------------------------------
May 16 2024 07:33PM [INFO] my-user-id: valid_user_id (test_code.py:50)
May 16 2024 07:33PM [INFO] my-client-id: valid_client_id (test_code.py:51)
May 16 2024 07:33PM [INFO] my-user-id: valid_user_id (test_code.py:52)
May 16 2024 07:33PM [INFO] my-client-id: valid_client_id (test_code.py:53)
PASSED
When I execute the same code via Google cloud build, this is what I see in the logs I’ve printed:
Step #1: ------------------------------ Captured log setup ------------------------------
Step #1: INFO test_code:test_code.py:25 my-user-id: $MY_USER_ID
Step #1: INFO test_code:test_code.py:26 my-client-id: $MY_CLIENT_ID
Step #1: INFO test_code:test_code.py:27 my-user-id: $MY_USER_ID
Step #1: INFO test_code:test_code.py:28 my-client-id: $MY_CLIENT_ID
Step #1: INFO test_code:test_code.py:29 MY_USER_ID: $MY_USER_ID
Step #1: INFO test_code:test_code.py:30 MY_CLIENT_ID: $MY_CLIENT_ID
Step #1: ------------------------------ Captured log call -------------------------------
Step #1: INFO test_code:test_code.py:50 my-user-id: $MY_USER_ID
Step #1: INFO test_code:test_code.py:51 my-client-id: $MY_CLIENT_ID
Step #1: INFO test_code:test_code.py:52 my-user-id: $MY_USER_ID
Step #1: INFO test_code:test_code.py:53 my-client-id: $MY_CLIENT_ID
Step #1: =========================== short test summary info ============================
here’s my setup:
qa
|-- conftest.py
|-- pytest.ini
|-- build
|-- cloudbuild.yaml
|-- api
|-- test_code.py
conftest.py
import pytest
def pytest_addoption(parser):
parser.addoption("--my-client-id", action="store")
parser.addoption("--my-user-id", action="store")
parser.addoption("--my-tenant-id", action="store")
parser.addoption("--version-name", action="store")
@pytest.fixture(scope='session')
def request_params(request):
my_user_id = request.config.getoption("--my-user-id")
my_tenant_id = request.config.getoption("--my-tenant-id")
my_client_id = request.config.getoption("--my-client-id")
version_name = request.config.getoption("--version-name")
return params(my_user_id, my_tenant_id, my_client_id, version_name)
class params:
def __init__(self, my_user_id, my_tenant_id, my_client_id, version_name):
self.my_user_id = my_user_id
self.my_tenant_id = my_tenant_id
self.my_client_id = my_client_id
self.version_name = version_name
test_code.py
import logging
import pytest
import requests
import os.path
import json
import time
LOGGER = logging.getLogger(__name__)
def setup_module(request_params):
global my_user_id
global my_tenant_id
global my_session_id
global my_client_id
global my_base_url
global version
my_user_id = os.environ.get("MY_USER_ID", "not_found")
my_client_id = os.environ.get("MY_CLIENT_ID", "not_found")
my_tenant_id = os.environ.get("MY_TENANT_ID", "not_found")
my_base_url = 'https://myapp.com/version/acc'
LOGGER.info('my-user-id: %s' % my_user_id)
LOGGER.info('my-client-id: %s ' % my_client_id)
LOGGER.info('os.environ.my-user-id: %s' % os.environ.get("my_USER_ID", "not_found"))
LOGGER.info('os.environ.my-client-id: %s ' % os.environ.get("my_CLIENT_ID", "not_found"))
LOGGER.info('request_params.MY_USER_ID: %s' % str(request_params.my_user_id))
LOGGER.info('request_params.MY_CLIENT_ID: %s' % str(request_params.my_client_id))
@pytest.fixture(scope="session", autouse=True)
def set_env(request_params):
os.environ["MY_USER_ID"] = str(request_params.my_user_id)
os.environ["MY_TENANT_ID"] = str(request_params.my_tenant_id)
os.environ["MY_CLIENT_ID"] = str(request_params.my_client_id)
os.environ["VERSION"] = str(request_params.version_name)
@pytest.mark.smoke
def test_audit(request_params):
version = str(request_params.version_name)
url = my_base_url + "/" + version + "/1.0/audit"
headers = {
'my-user-id': my_user_id,
'my-client-id': my_client_id
}
LOGGER.info('my-user-id: %s' % my_user_id)
LOGGER.info('my-client-id: %s ' % my_client_id)
LOGGER.info('my-user-id: %s' % os.environ.get("MY_USER_ID", "not_found"))
LOGGER.info('my-client-id: %s ' % os.environ.get("MY_CLIENT_ID", "not_found"))
r = requests.get(url, headers=headers)
assert r.status_code == 200
This is what my cloudbuild.yaml looks like:
steps:
# Smoke test
- name: 'python'
entrypoint: 'pip'
args: ['install', '-r', 'requirements.txt', '--user']
- name: 'python'
entrypoint: 'python'
args: [ '-m', 'pytest', '-m', 'smoke', '-v', '--my-user-id', '$$MY_USER_ID', '--my-tenant-id', '$$MY_TENANT_ID', '--my-client-id', '$$MY_CLIENT_ID', '--version-name', '${_VERSION}' ]
secretEnv: ['MY_CLIENT_ID', 'MY_USER_ID', 'MY_TENANT_ID']
env:
- 'VERSION=${_VERSION}'
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/MY-client-id/versions/1
env: 'MY_CLIENT_ID'
- versionName: projects/$PROJECT_ID/secrets/MY-user-id/versions/1
env: 'MY_USER_ID'
- versionName: projects/$PROJECT_ID/secrets/MY-tenant-id/versions/1
env: 'MY_TENANT_ID'
substitutions:
_VERSION: "1"
What I’ve tried so far :
- Changing the scope for the set_env method from “session” to “module” makes it work. The code executes correctly on cloud build and this code stops working when I test locally from my mac.
- Changing the scope to “function” breaks in both local and cloud build.
My goal is: if I am passing the same variables via pytest command in local or google cloud build, it should run in both places.