@@ -90,8 +90,13 @@ class WatchlistTestCase(unittest.TestCase):
9090
9191 def setUp (self ):
9292 # 使用测试配置创建程序实例
93- app = create_app(config_name = ' testing' )
94- # 创建数据库和表
93+ self .app = create_app(config_name = ' testing' )
94+ # 创建程序上下文
95+ self .context = self .app.app_context()
96+ # 激活上下文
97+ self .context.push()
98+
99+ # 创建数据库和表
95100 db.create_all()
96101 # 创建测试数据,一个用户,一个电影条目
97102 user = User(name = ' Test' , username = ' test' )
@@ -101,12 +106,13 @@ class WatchlistTestCase(unittest.TestCase):
101106 db.session.add_all([user, movie])
102107 db.session.commit()
103108
104- self .client = app.test_client() # 创建测试客户端
105- self .runner = app.test_cli_runner() # 创建测试命令运行器
109+ self .client = self . app.test_client() # 创建测试客户端
110+ self .runner = self . app.test_cli_runner() # 创建测试命令运行器
106111
107112 def tearDown (self ):
108113 db.session.remove() # 清除数据库会话
109114 db.drop_all() # 删除数据库表
115+ self .context.pop() # 清除上下文
110116
111117 # 测试程序实例是否存在
112118 def test_app_exist (self ):
@@ -127,9 +133,16 @@ class TestingConfig(BaseConfig):
127133
128134这里将 ` TESTING ` 设为 ` True ` 来开启测试模式,这样在出错时不会输出多余信息;然后将 ` SQLALCHEMY_DATABASE_URI ` 设为 ` 'sqlite:///:memory:' ` ,这会使用 SQLite 内存型数据库,不会干扰开发时使用的数据库文件。你也可以使用不同文件名的 SQLite 数据库文件,但内存型数据库速度更快。
129135
136+ 某些程序操作需要在激活 Flask 上下文时执行,比如前面介绍的 ` url_for() ` 函数,或是创建数据库表的 ` db.session.create_all() ` 操作。我们在 ` setUp() ` 方法中创建并激活程序上下文:
137+
138+ ``` python
139+ self .context = self .app.app_context()
140+ self .context.push()
141+ ```
142+
130143接着,我们调用 ` db.create_all() ` 创建数据库和表,然后添加测试数据到数据库中。在 ` setUp() ` 方法最后创建的两个类属性分别为测试客户端和测试命令运行器,前者用来模拟客户端请求,后者用来触发自定义命令,下一节会详细介绍。
131144
132- 在 ` tearDown() ` 方法中,我们调用 ` db.session.remove() ` 清除数据库会话并调用 ` db.drop_all() ` 删除数据库表。测试时的程序状态和真实的程序运行状态不同,所以需要调用 ` db.session.remove() ` 来确保数据库会话被清除。
145+ 在 ` tearDown() ` 方法中,我们调用 ` db.session.remove() ` 清除数据库会话并调用 ` db.drop_all() ` 删除数据库表。测试时的程序状态和真实的程序运行状态不同,所以需要调用 ` db.session.remove() ` 来确保数据库会话被清除。最后调用 ` self.context.pop() ` 清除上下文。
133146
134147
135148### 测试程序功能
468481
469482``` bash
470483$ coverage report
471- Name Stmts Miss Cover
472- -------------------------------------------
473- watchlist\_ _init__.py 25 1 96%
474- watchlist\c ommands.py 35 1 97%
475- watchlist\e rrors.py 8 2 75%
476- watchlist\m odels.py 16 0 100%
477- watchlist\e xtensions.py 77 2 97%
478- ...
479- -------------------------------------------
480- TOTAL 161 6 96%
484+ Name Stmts Miss Cover
485+ ------------------------------------------------------
486+ watchlist/__init__.py 23 0 100%
487+ watchlist/blueprints/__init__.py 0 0 100%
488+ watchlist/blueprints/auth.py 28 0 100%
489+ watchlist/blueprints/main.py 61 1 98%
490+ watchlist/commands.py 41 1 98%
491+ watchlist/errors.py 11 2 82%
492+ watchlist/extensions.py 13 3 77%
493+ watchlist/models.py 20 0 100%
494+ watchlist/settings.py 15 0 100%
495+ ------------------------------------------------------
496+ TOTAL 212 7 97%
481497```
482498
483499测试覆盖率报告列出了包内文件的覆盖率情况,包括每个文件的行数(Stmts),没测试到的代码行数(Miss),以及测试覆盖率(Cover)。
484500
485- 你还可以使用 coverage html 命令获取详细的 HTML 格式的覆盖率报告,它会在当前目录生成一个 htmlcov 文件夹,打开其中的 index.html 即可查看覆盖率报告。点击文件名可以看到具体的代码覆盖情况,如下图所示:
486-
487- ![ 覆盖率报告] ( images/9-1.png )
501+ 你还可以使用 ` coverage html ` 命令获取详细的 HTML 格式的覆盖率报告,它会在当前目录生成一个 htmlcov 文件夹,打开其中的 index.html 即可查看覆盖率报告。点击文件名可以看到具体的代码覆盖情况,如下图所示:
502+ ![ Coverage report] ( images/9-1.png )
488503
489- 记得在 .gitignore 文件后追加下面两行,忽略掉生成的覆盖率报告文件:
504+ 最后记得在 .gitignore 文件后追加下面两行,忽略掉生成的覆盖率报告文件:
490505
491506```
492507htmlcov/
0 commit comments