Environments
Environments let you define variables for different contexts like development, staging, and production. Switch between them without changing your tests.
Creating an Environment File
Create a .nornenv file with your environments:
# Common variables (always available)
var timeout = 30000
var apiVersion = v1
[env:dev]
var baseUrl = http://localhost:3000
var apiKey = dev-key-12345
[env:staging]
var baseUrl = https://staging.api.example.com
var apiKey = staging-key-67890
[env:prod]
var baseUrl = https://api.example.com
secret apiKey = prod-key-secret Importing Shared Environment Files
Split shared settings into separate .nornenv files and import them at the top of your main environment file. Import paths are relative to the file that declares them.
var timeout = 30000
[env:dev]
var baseUrl = http://localhost:3000
[env:staging]
var baseUrl = https://staging.api.example.com import "./shared/base/.nornenv"
var apiVersion = v1
[env:dev]
var paymentsPath = /payments
[env:staging]
var paymentsPath = /payments Then use the merged variables in your tests:
GET {{baseUrl}}{{paymentsPath}}/health
X-API-Version: {{apiVersion}} Keep import statements at the top of the file. Imports can chain through other .nornenv files, but duplicate variable names in the same scope are treated as configuration errors.
Using Environment Variables
Reference variables in your .norn files:
GET {{baseUrl}}/users
Authorization: Bearer {{apiKey}} {{name}} keeps the normal lookup order. If a file variable, local variable, or sequence parameter shadows an environment variable, use {{$env.name}} to read the active environment value explicitly.
var baseUrl = https://example.local
print "local={{baseUrl}} env={{$env.baseUrl}}"
GET {{$env.baseUrl}}/users Reusable Environment Templates
Values in .nornenv can reference other environment values with {{name}} or {{$env.name}}. This is useful for SQL connection strings that share the same shape across environments but need different hosts, databases, or credentials.
connectionString appDb = Server={{appDb_server}};Database={{appDb_database}};User ID={{appDb_user}};Password={{appDb_password}};
[env:dev]
var appDb_server = localhost
var appDb_database = CustomerDev
var appDb_user = norn_dev
secret appDb_password = dev-password
[env:prelive]
var appDb_server = sql01.company.local
var appDb_database = CustomerDb
var appDb_user = norn_runner
secret appDb_password = ENC[...] Templates resolve from the active merged environment, including imported files. A common value outside any [env:...] section can reference environment-specific variables. A value inside an [env:...] section can reference common variables, but it cannot reference another environment-specific variable.
Keep connection templates in .nornenv; do not pass connection details from .norn sequences.
Refactoring Stage and Region Matrices
If a .nornenv file has a flat set of environments named like dev_us, dev_uk, prod_us, and prod_uk, Norn can refactor the repeated values into stage and region templates.
[env:dev_us]
var baseUrl = https://dev.example.com
var dbHost = us-db.local
[env:dev_uk]
var baseUrl = https://dev.example.com
var dbHost = uk-db.local
[env:prod_us]
var baseUrl = https://api.example.com
var dbHost = us-db.local
[env:prod_uk]
var baseUrl = https://api.example.com
var dbHost = uk-db.local [template:dev]
var baseUrl = https://dev.example.com
[template:prod]
var baseUrl = https://api.example.com
[template:us]
var dbHost = us-db.local
[template:uk]
var dbHost = uk-db.local
[env:dev_us extends dev, us]
[env:dev_uk extends dev, uk]
[env:prod_us extends prod, us]
[env:prod_uk extends prod, uk] The refactor only lifts values that are consistent across a stage or region. Values that are missing in some environments, connection strings, and true per-environment overrides stay in the leaf [env:...] sections. Secret declarations stay secret only where the generated declaration needs them.
Switching Environments
Use the Command Palette (Cmd+Shift+P) and select:
Norn: Select Environment Or click the environment name in the status bar. In VS Code, the active environment is remembered per nearest .nornenv file and persists for the workspace, so different folders in a monorepo can keep different active selections.
Secret Variables
Mark sensitive variables as secrets to prevent them from appearing in logs:
[env:prod]
var baseUrl = https://api.example.com
secret apiKey = prod-key-secret
secret password = ENC[NORN_AGE_V1:kid=team-main:abc123xyz] Secret values are automatically redacted in:
- Response panel output
- CLI logs
- Test reports
Environment in CLI
Specify the environment when running tests:
norn tests/ --env staging Default Values
Variables defined outside any section are available in all environments:
# Available in all environments
var timeout = 30000
[env:dev]
var baseUrl = http://localhost:3000
[env:staging]
var baseUrl = https://staging.example.com Nested Values
Use JSON for complex values:
[env:dev]
var testUser = {"id": 1, "name": "Test User"} Access nested properties:
GET {{baseUrl}}/users/{{testUser.id}}