chalice icon indicating copy to clipboard operation
chalice copied to clipboard

Environment variables producing errors during testing

Open Maxim-Durand opened this issue 3 years ago • 3 comments

Hello, firstly I'd like to thank you for Chalice ! It's really easy to use and it worked very well to develop my API.

I use environment variables from .chalice/config.json in my app and it works fine for local and deployment.

But now that I want to write tests for my app, those environment variables produce errors.

I tried following the documentation about testing with environment variables (https://aws.github.io/chalice/topics/testing.html#environment-variables) but to no avail.

Here is the problematic code in question from tests/test_app.py where 'dev' is the stage name with all environment variables.

from chalice.test import Client

from app import app
def test_myPath():
    with Client(app, stage_name='dev') as client:
        response = client.http.get('/myPath')
        assert response.status_code == 200

Then when I run :

py.test tests/test_app.py

I get :

================================================================================================================= ERRORS ================================================================================================================= 
___________________________________________________________________________________________________ ERROR collecting tests/test_app.py ___________________________________________________________________________________________________ 
tests\test_app.py:5: in <module>
    from app import app
app.py:21: in <module>
    MY_URL = os.environ["MY_URL"]
C:\Python310\lib\os.py:679: in __getitem__
    raise KeyError(key) from None
E   KeyError: 'MY_URL'

I checked by printing print(os.environ) from tests/test_app.py and the environment variables from .chalice/config.json aren't there.

Maxim-Durand avatar Feb 28 '22 20:02 Maxim-Durand

I am running into this issue as well...

juls858 avatar Apr 11 '22 22:04 juls858

I discovered a few things by looking at the relevant test client code:

https://github.com/aws/chalice/blob/a87dd3fd30a441206e99cd1e05e826c1b30315d4/chalice/test.py#L34-L46

  • Any errors loading the config are silently ignored

  • The config file .chalice/config.json is loaded relative to the project_dir (e.g. runtime), which defaults to the current directory. This means that if you're running your tests outside of that directory, the config file won't get loaded. You can work around this by:

    • Putting your test_*.py files in the runtime directory, and running pytest from there (hack, not recommended)
    • Instantiating Client(app, project_dir=runtime_dir), where runtime_dir is something like Path(__file__).parent.parent / "runtime"
  • The configuration is only used for client.http and client.lambda_. That means if you're reading os.environ outside of @app.route/@app.lambda_function (or code they execute), the environment variables won't be set.

bhrutledge avatar Apr 13 '22 11:04 bhrutledge

tests\test_app.py:5: in <module>
    from app import app
app.py:21: in <module>
    MY_URL = os.environ["MY_URL"]
C:\Python310\lib\os.py:679: in __getitem__
    raise KeyError(key) from None
E   KeyError: 'MY_URL'

This looks like MY_URL is a module-level variable, is that correct? I've run into similar issues; as it turns out, environment variables are only set in the lambda function's scope when using the test client (if you think about it, it makes sense: Before you can initialize the test client, you need to import the app variable from the app module so that module-level code will be evaluated, including global variables). If you move this module-level variable into the lambda function, it should work.

waveFrontSet avatar Apr 13 '22 15:04 waveFrontSet

You probably figured it out already @Maxim-Durand. For me I had to do two things to get my tests working with my fake env vars:

  1. Set the Chalice test client's stage to local. I don't have that configured, but I needed something that was dev
  2. In my conftest.py file. before I do from app import app, I set all the env vars for testing. My app loads secret manager at start up, so we did this so the import only triggers the mock secret manager instead of the real one

msanatan avatar Feb 01 '23 21:02 msanatan