为了加快测试速度,使用基于内存的 sqlite 会更好,但偶尔仍然有必要使用 MySQL 进行更接近生产的测试。 为了避免枯燥的讨论/抽象的问题,下面的代码插入了几个词并确认它们在数据库中,对于刚刚提到的两种类型的 SQL 数据库。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import unittest
db = SQLAlchemy()
TEST_DATABASE_URL_MEMORY = 'sqlite:///:memory:'
TEST_DATABASE_URL_MYSQL = 'mysql+pymysql://root:@127.0.0.1:3306/somewords'
def create_app(db_url):
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = db_url
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
return app
class Word(db.Model):
__tablename__ = 'words'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
word = db.Column(db.String(32), index=True)
class TestInsertion(unittest.TestCase):
def manual_set_up(self, db_url):
self.app = create_app(db_url)
self.app_context = self.app.app_context()
self.app_context.push()
db.drop_all()
db.create_all()
def insert(self):
words = ['hello', 'world']
for word in words:
w = Word(word=word)
db.session.add(w)
db.session.commit()
for word in words:
assert Word.query.filter_by(word=word).first() is not None
def test_dbs(self):
for db_url in [TEST_DATABASE_URL_MEMORY,
TEST_DATABASE_URL_MYSQL]:
self.manual_set_up(db_url)
self.insert()
第一个 (sqlite) 通过。第二次失败:
E sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1049, "Unknown database 'somewords'")
我们可以在每次运行测试时创建数据库
> mysql -u root -p
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> create database somewords;
Query OK, 1 row affected (0.02 sec)
mysql> quit;
但这排除了自动化测试,所以我猜我遗漏了一些基本的东西。
如何通过自动创建数据库,在无人值守的情况下运行上述测试?
更新
1.0 的测试示例, 1.1 ,教程 (flask/examples/tutorial/tests/conftest.py) 使用 tempfile.mkstemp(),这看起来是个不错的方法。无需担心设置名称和创建数据库,甚至无需关心(随机且可丢弃的)数据库名称。数据库创建部分如何/在哪里完成?
import tempfile
db_fd, db_path = tempfile.mkstemp()
最佳答案
通过对 manual_set_up 和 test_dbs 进行一些修改,我能够运行代码。
对于 mysql 数据库,我从 db_url 中删除了数据库名称。并且 db.drop_all() 也失败了,因为数据库不存在所以我放入 try/except 并在此处传递异常。然后在 db.create_all() 之前,我创建了一个绕过 db_url 的 sqlachemy 引擎,它没有数据库名称 db.create_engine(db_url)。
# your imports ...
import sqlalchemy.exc
#...
TEST_DATABASE_URL_MYSQL = 'mysql+pymysql://root:@127.0.0.1:3306/'
def manual_set_up(self, db_url, db_kind, db_name=None):
if db_kind == "mysql":
self.app = create_app(db_url + db_name)
else:
self.app = create_app(db_url)
self.app_context = self.app.app_context()
self.app_context.push()
try:
db.drop_all()
except sqlalchemy.exc.InternalError as e:
if "unknown database" in str(e.args[0]).lower():
pass
try:
db.create_all()
except sqlalchemy.exc.InternalError as e:
if "unknown database" in str(e.args[0]).lower():
db.create_engine(db_url, {}).execute(f"CREATE DATABASE IF NOT EXISTS {db_name};")
db.create_all()
def test_dbs(self):
for args in [(TEST_DATABASE_URL_MEMORY, "sqlite"),
(TEST_DATABASE_URL_MYSQL, "mysql", "somewords")]:
self.manual_set_up(*args)
self.insert()
关于python - 自动创建用于测试的数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57047587/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere