【问题标题】:How to get Sphinx doctest to reset the Django database after each test?每次测试后如何让 Sphinx doctest 重置 Django 数据库?
【发布时间】:2021-01-27 16:43:38
【问题描述】:

[TL;DR] 当使用 Sphinx 的 make doctest 时,测试中创建的 Django 模型被提交到数据库;我们如何防止它们自动提交或在每次测试之间重置数据库(使用与pytest 类似的方法)?

设置

我使用脚本创建了一个基本的 Django 应用程序:

python -m pip install django sphinx pytest pytest-django pytest-sphinx
django-admin startproject project_name
cd project_name
mkdir project_name/app
python manage.py startapp app project_name/app
touch pytest.ini
touch conftest.py
mkdir docs
cd docs ; sphinx-quickstart ; cd ..

(在sphinx-quickstart 中创建单独的源目录和构建目录。)

然后:

  1. 已将project_name/app/models.py 更改为:
"""Models for the test application."""

from django.db import models


class Animal(models.Model):
    """A django model for an animal.
    
    .. rubric: Example
    
    .. testsetup:: animal
    
        from project_name.app.models import Animal

    .. testcode:: animal
    
        frog = Animal.objects.create(name="frog")
        print( frog )
    
    .. testoutput:: animal
    
        Animal object (1)
    """
    name = models.CharField(max_length=200)

  1. 编辑project_name/settings.py 以将'project_name.app' 添加到INSTALLED_APPS
  2. 编辑docs/source/conf.py 以在“路径设置”下添加行:
import os
import sys
import django

sys.path.insert(0, os.path.abspath('../..'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'project_name.settings'
django.setup()

并在“常规配置”下设置:

extensions = [
  "sphinx.ext.autodoc",
  "sphinx.ext.doctest",
]
  1. docs/source/index.rst 替换为:
.. toctree::
   :maxdepth: 2
   :caption: Contents:

Project Name Documentation
==========================

.. currentmodule:: project_name.app.models

.. autoclass:: Animal
  1. pytest.ini 替换为:
[pytest]
DJANGO_SETTINGS_MODULE = project_name.settings
addopts = --doctest-modules
  1. conftest.py 替换为:
import pytest

@pytest.fixture(autouse=True)
def enable_db_access_for_all_tests(db):
    pass
  1. 然后运行:
python manage.py makemigrations
python manage.py migrate

问题

当我运行pytest时,文档中的测试每次都运行并通过;但是,当我使用 Sphinx 并在 docs 子目录中运行 make doctest 时,它第一次通过,然后随后失败,因为它每次都会创建一个新的 Animal 实例并将其提交到数据库和不会重新创建数据库。

Running Sphinx v3.4.3
loading pickled environment... done
building [mo]: targets for 0 po files that are out of date
building [doctest]: targets for 1 source files that are out of date
updating environment: 0 added, 0 changed, 0 removed
looking for now-outdated files... none found
running tests...

Document: index
---------------
**********************************************************************
File "../../project_name/app/models.py", line ?, in animal
Failed example:
    frog = Animal.objects.create(name="frog")
    print( frog )
Expected:
    Animal object (1)
Got:
    Animal object (2)
**********************************************************************

如何更改docs/source/conf.py(或其他适当的脚本)以使用类似于pytest 的方法,以便每次都通过Sphinx doctest(无需删除并重新创建数据库)?

(我不想更改文档中的单元测试;我想确保数据库已重置或数据未提交并在每次测试后回滚。)

【问题讨论】:

  • 不是一个完整的答案,但是如果没有 Sphinx,您将如何运行 pytest 以不提交和回滚事务?如果你有这样的例子,也许你可以把它应用到 doctests 和 Sphinx 上?
  • @StevePiercy 你只需运行pytest 并安装pytest-django 包;我相信,它被设置为(开箱即用)使用假数据库或关闭AUTOCOMMIT,以便回滚事务。 Sphinx 使用一个调用 sphinx-build 的 make 文件,该文件使用 sphinx.ext.doctest 进而调用 doctest 包....所以解决方案可能是构建一个自定义 sphinx 扩展,其中大部分代码来自 @987654355 @ 调用pytest 而不是doctest
  • 挖掘更多,pytest-django 添加了一个夹具,sets up the Django test environment 用于其测试。

标签: python django pytest python-sphinx doctest


【解决方案1】:

对此的快速(且肮脏)的解决方案是绕过问题并在运行测试之前刷新数据库:

python ./manage.py migrate
python ./manage.py flush
./docs/make doctest
  • 首先应用迁移,以防测试 SQLite 数据库不存在;那么
  • 数据库已刷新(您可以使用--no-input 标志跳过输入提示。但是,如果意外应用于生产数据库,则可能会很危险,因此默认情况下不包括在内);和
  • 最后,在空数据库上运行文档测试。

这在简单示例中有效,但如果有许多示例正在运行,它们创建同一模型的多个实例(并且每个实例都会获得不同的自动生成的 id 值)并且测试在非-确定性顺序。

【讨论】:

    猜你喜欢
    • 2019-01-01
    • 2013-11-08
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多