Skip to content

Providing guidance for __app__ in the face of unit testing #469

@brettcannon

Description

@brettcannon

If you look at the unit testing example, you will notice it uses relative imports. If you look earlier in that same page you will notice that the suggested folder structure has the folder containing the function files be named FunctionApp. The problem is that if the unit testing code were to switch to using absolute imports and thus import from __app__, then the unit testing example will fail with an ImportError.

I think there are two ways to solve this. One is to not encourage people to use __app__. If you do this then the current recommended practice of making FunctionApp the folder you commit to git and naming it appropriately for your project can continue. That does also mean, though, that beyond discouraging absolute imports via __app__ you will also need to document how run test runners like pytest such that they know where the root of the project is. This is important because if the unit testing example were to suddenly include an import for shared code -- from ..SharedCode import myFirstHelperFunction as listed in the folder structure example -- it would fail as pytest . from within your project/git checkout wouldn't know where the module root was (it works now because pytest just thinks myapp is the top-level package thanks to it only referencing code from within that folder). And you can't do pytest .. as that would cause pytest to search all folders in the parent folder for tests which could be a lot if you keep all of your git clones in a single directory (e.g. all of my GitHub clones are in a Repositories/ folder, so pytest .. would search 5 other repositories on the machine I'm typing from). And so some guidance for how people should tell pytest how to run their tests appropriately would be required (on top of advising people not to use __app__).

The other option is to change the folder structure guidance to be more like the following (see the functions version of pvscbot to see this working in a deployed function):

FunctionApp
 | - __app__
 | | - __init__.py
 | | - MyFirstFunction
 | | | - __init__.py
 | | | - function.json
 | | - MySecondFunction
 | | | - __init__.py
 | | | - function.json
 | | - SharedCode
 | | | - myFirstHelperFunction.py
 | | | - mySecondHelperFunction.py
 | | - host.json
 | | - requirements.txt

By embracing the fact that the package needs to be named __app__ you avoid all of the above mentioned issues with pytest and breaking unit tests if you start using absolute imports without naming your git repository appropriately. It also has a nice side-effect of letting people keep their tests and related requirements specifications outside of the folder that gets deployed to Azure (which should speed up deployment; see the sample repo I linked to above to see how to make a dev-requirements.txt refer to __app__/requirements.txt to practice DRY with dependencies).

The problem is this solution obviously goes against the guidance to have the folder that func init creates for you be what becomes your git repository (e.g. the example on how to use Azure Pipelines for CD won't work out-of-the-box as you now need to deploy a sub-folder of your repository). It also means that func new is creating a .vscode folder in the wrong location.

Anyway, it would be great to solve this somehow as unit testing stateless functions on Azure is really nice and simple thanks to HttpRequest having a constructor that is easy to work with.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions