![](/img/trans.png)
[英]Should I share GCP Artifact Registry instances between different stages like production and test?
[英]Select different dataset when testing | Separate test from production
这个问题部分是关于如何测试外部依赖项(又名集成测试),部分是关于如何使用 Python 来实现它,因为 SQL 具体是 BigQuery。 因此,非常欢迎仅回答“这是您应该如何进行集成测试”的答案。
在我的项目中,我有两个不同的数据集
'project_1.production.table_1'
'project_1.development.table_1'
在运行我的测试时,我想调用开发环境。 但是如何正确地将它与我的生产代码分开,因为我不想将我的生产代码与测试(设置)代码混淆。
生产代码如下所示:
def find_data(variable_x: string) -> DataFrame:
query = '''
SELECT *
FROM `project_1.production.table_1`
WHERE foo = @variable_x
'''
job_config = bigquery.QueryJobConfig(
query_parameters=[
bigquery.ScalarQueryParameter(
name='foo', type_="STRING", value=variable_x
)
]
)
df = self.client.query(
query=query, job_config=job_config).to_dataframe()
return df
python-dotenv 模块可用于区分生产和开发,就像我对代码的某些部分所做的那样。 问题是 bigQuery 不允许参数化数据集。 (为了防止 SQL 注入,我认为)请参阅运行参数化查询文档
从文档
参数不能用作标识符、列名、表名或查询的其他部分的替代品。
因此,将环境变量作为数据集名称是不可能的。
我可以添加一个 if production == True 评估和 select 数据集。 但是,这会导致我的生产代码中的测试/调试代码。 我想尽可能地避免它。
from os import getenv
def find_data(variable_x : string) -> Dataframe:
load_dotenv()
PRODUCTION = getenv("PRODUCTION")
if PRODUCTION == TRUE:
*Execute query on project_1.production.table_1*
else:
*Execute query on project_1.development.table_1*
job_config = (*snip*)
df = (*snip*)
return df
制作生产代码的副本并设置测试代码,以便调用开发数据集。
这会导致代码重复(一个在生产代码中,一个在测试代码中)。 这种重复的结果会导致代码的不匹配,可能随着时间的推移function的执行发生变化。 所以我认为这个解决方案不是“拥抱变化”
也许这个 function 在我的测试代码中根本不需要调用。 只需获取此查询结果的片段,并将结果用作“数据注入”到依赖此结果的测试中。 但是,我需要稍微调整一下我的架构。
上述解决方案并不能完全满足我。 我想知道是否有另一种方法可以解决这个问题,或者上述解决方案之一是否可以接受?
看起来字符串格式(有时称为字符串插值)可能足以让您到达您想要的位置。 您可以用以下代码替换 function 的第一部分:
query = '''
SELECT *
FROM `{table}`
WHERE foo = @variable_x
'''.format(table = getenv("DATA_TABLE"))
这是有效的,因为查询只是一个字符串,您可以在将它传递到 BigQuery 库之前对它做任何您想做的事情。 String.format
允许我们替换字符串中的值,这正是我们所需要的(有关String.format
的更深入解释,请参阅本文)
重要的安全注意事项:通常将 SQL 查询作为纯字符串操作是一种不好的安全做法(正如我们在此处所做的那样),但由于您控制应用程序的环境变量,因此在这种特殊情况下应该是安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.