Quelle est la meilleure façon d’écrire des spécifications pour du code qui dépend des variables d’environnement?

Je teste du code qui tire sa configuration des variables d’environnement (définies par les vecteurs de configuration Heroku en production, pour le développement local que j’utilise comme contremaître).

Quelle est la meilleure façon de tester ce type de code avec RSpec?

Je suis venu avec ceci:

before :each do ENV.stub(:[]).with("AWS_ACCESS_KEY_ID").and_return("asdf") ENV.stub(:[]).with("AWS_SECRET_ACCESS_KEY").and_return("secret") end 

Si vous n’avez pas besoin de tester différentes valeurs des variables d’environnement, je suppose que vous pouvez les définir dans spec_helper place.

Ça marcherait.

Une autre méthode consisterait à placer une couche d’indirection entre votre code et les variables d’environnement, comme une sorte d’object de configuration facile à simuler.

Vous pouvez également modifier la constante:

 stub_const('ENV', {'AWS_ACCESS_KEY_ID' => 'asdf'}) 

Ou, si vous voulez toujours le rest de l’ENV:

 stub_const('ENV', ENV.to_hash.merge('AWS_ACCESS_KEY_ID' => 'asdf')) 

Comme Heroku le suggère , vous pouvez utiliser le fichier .env de Foreman pour stocker les variables d’environnement pour le développement.

Si vous faites cela, vous pouvez utiliser le foreman run pour exécuter vos spécifications:

 foreman run bundle exec rspec spec 

J’éviterais ENV.stub (: []) – cela ne fonctionne pas si d’autres choses utilisent ENV comme pry (vous aurez une erreur à propos de la nécessité de stub DISABLE_PRY).

stub_const fonctionne bien comme déjà souligné.

Vous pouvez utiliser https://github.com/littleowllabs/stub_env pour y parvenir. Il vous permet de supprimer des variables d’environnement individuelles sans les écraser toutes comme votre solution l’a suggéré.

Installez la gem puis écrivez

 before :each do stub_env('AWS_ACCESS_KEY_ID', 'asdf') stub_env('AWS_SECRET_ACCESS_KEY','secret') end 

Ce que vous voulez, c’est le joyau dotenv .

Exécuter des tests sous contremaître, comme le suggère @ciastek, fonctionne parfaitement lorsque vous exécutez des spécifications à partir de l’interface de ligne de commande. Mais cela ne m’aide pas à exécuter les spécifications avec Ruby Test dans Sublime Text 2. Dotenv fait exactement ce que vous voulez, de manière transparente.

Si vous utilisez dotenv pour configurer votre environnement pendant les tests, mais que vous devez modifier une variable env pour un test spécifique, l’ approche suivante peut être utile.

Une méthode plus simple que le remplacement de ENV consiste à remplacer l’environnement pendant la durée du test, puis à le restaurer comme suit:

 with_environment("FOO" => "baz") do puts ENV.fetch("FOO") end 

En utilisant un assistant comme celui-ci (de la source Homebrew ):

 module Test module Helper module Env def with_environment(partial_env) old = ENV.to_hash ENV.update partial_env begin yield ensure ENV.replace old end end end end end 

En vous ensure l’environnement d’origine est restauré même si le test échoue.

Il y a une comparaison pratique des méthodes de définition et de modification des variables d’environnement lors des tests, y compris le stubing de l’ ENV , le remplacement des valeurs avant / après le test et des gemmes comme ClimateControl.

Cette syntaxe fonctionne pour moi:

 module SetEnvVariable def set_env_var(name, value) # Old Syntax # ENV.stub(:[]) # ENV.stub(:[]).with(name).and_return(value) allow(ENV).to receive(:[]) # stub a default value first if message might be received with other args as well. allow(ENV).to receive(:[]).with(name).and_return(value) end end