I am a None ORM user, I prefer to use plain text queries, I took that course on free code camp on FastAPI but almost the whole course revolves around ORMs so I struggle to implement a number of concepts found in that course.
My main struggle is when I write tests for my endpoints I need to use a test database rather than my development database, I am using testing.postgres to create the testing database and this is the code I am using:
client = TestClient(app)
class TestUser:
def setup_method(self, method):
self.postgres = testing.postgresql.Postgresql(cache_initialized_db=True)
self.db = psycopg2.connect(**self.postgres.dsn())
def teardown_method(self, method):
self.db.close()
def test_get_users(self):
res = client.get("/users")
assert res.status_code == 200
assert res.headers["content-type"] == "application/json"
my question is how to make my tests and cruds send queries to the test database, not the development database.
where is the link that I should add here?
Edit: this is the code I use for connection with database, I am not using a dependency for it:
while True:
try:
conn = psycopg2.connect(
database=settings.database,
user=settings.user,
port=settings.port,
password=settings.password,
cursor_factory=RealDictCursor,
)
cr = conn.cursor()
console.print(
"[green bold]SUCCESS[/]: Connection To Database Established successfuly"
)
break
except psycopg2.OperationalError:
console.print(
"[red bold]FAILED[/]: Connection To Database Failed , Trying Again"
)
time.sleep(2)
Edit2: this is the settings segment:
load_dotenv()
class Settings(BaseSettings):
database: str
user: str
port: int
password: str
expiray: int
algorithm: str
secret_key: str
settings = Settings()
If you wanna use the test database rather than the development database you should create the testing database and let the backend application be able to find the testing database and use it.
Kareem, I suggest you create your Settings
instance from one or another .env
file, based on an ENVIRONMENT
variable:
import os
import sys
import pydantic
class Settings(pydantic.BaseSettings):
database: str
user: str
port: int
password: str
expiray: int
algorithm: str
secret_key: str
try:
ENVIRONMENT = os.environ['ENVIRONMENT']
except KeyError:
print('make sure to set an "ENVIRONMENT" env var')
sys.exit()
settings = Settings(_env_file=f'{ENVIRONMENT}.env', _env_file_encoding='utf-8')
This way, if you want to work with the testing database, you can do $ export ENVIRONMENT=test
and it will load the settings from a file called test.env
.
Does that make sense? Here are the docs for pydantic
's dotenv
support for BaseSettings
subclasses.
As an aside, since you're interested in doing as much as you can without the use of an ORM and perhaps other dependencies, you really don't need pydantic
for your purposes: You could simply change the above to something like:
import os
import sys
import types
import dotenv
try:
ENVIRONMENT = os.environ['ENVIRONMENT']
except KeyError:
print('make sure to set an "ENVIRONMENT" env var')
sys.exit()
db_settings_dict = dotenv.dotenv_values(f"{ENVIRONMENT}.env")
# to get dot notation as in your example
settings = types.SimpleNamespace(**db_settings_dict)
where test.env
contains things like
database=hey.there.com:8768
user=kareem
...
Below is the Script I was written to control the ENV variable from the.env file, before running the unicorn server you would load the.env file based on the ENV mode to determine what kinds of modes are working on then use conditions to set up the corresponding DB path and name.
import os
import sys
from colored import fg
from os import environ, path
from dotenv import load_dotenv, set_key
import dotenv
def unknown(option, args=None):
color = fg('red')
if args:
print(color + f'Unknown arguments: -{args}')
else:
print(color + f'Unknown option: -{option}')
print("usage: python3 config.py [option] [arguments]")
print("Try `python3 config.py --help for more information")
color = fg('white')
print(color)
def version():
basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir, '.env'))
color = fg('blue')
print(color + '[VERSION]: ' + environ.get('VER'))
color = fg('white')
print(color)
def env():
basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir, '.env'))
color = fg('blue')
print(color + '[ENV]: ' + environ.get('ENV'))
color = fg('white')
print(color)
def set_env(env):
dotenv_file = dotenv.find_dotenv()
basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir, '.env'))
color = fg('blue')
print(color + f"[Updating ENV] ... ... from {environ.get('ENV')} to {env}")
os.environ["ENV"] = env
set_key(dotenv_file, 'ENV', os.environ['ENV'])
print("[Successfully Update the 'ENV' from .env]")
color = fg('white')
print(color)
def doc():
color = fg('blue')
print(color + "usage: python3 config.py [option] [arguments]")
read_me = """
-v : current project version
-env : current project environment
-set ENV={env} : set project env 'DEV' or 'PROD'
"""
print(read_me)
color = fg('white')
print(color)
def action_handler(option, args):
if option == '-set':
args_list = args.split('=')
if args_list[0] == 'ENV' and (args_list[1] == 'DEV' or args_list[1] == 'PROD'):
set_env(args_list[1])
else:
unknown(option=option, args=args)
else:
unknown(option=option)
argvs = len(sys.argv)
if argvs == 1:
doc()
elif argvs == 2:
option = sys.argv[1]
if option == '--help':
doc()
elif option == '-v':
version()
elif option == '-env':
env()
else:
unknown(option)
elif argvs == 3:
option, args = sys.argv[1], sys.argv[2]
action_handler(option, args)
else:
pass
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.