1

我想更好地编写这个测试:

def test_profile_created(self):
        self.client.post(reverse('registration_register'), data={
            'username':'ygam',
            'email':'ygam@example.com',
            'password1':'ygam',
            'password2':'ygam'
        })
        """
        Test if a profile is created on save
        """
        user = User.objects.get(username='ygam')
        self.assertTrue(UserProfile.objects.filter(user=user).exists())

我刚刚在 django-registration 测试中发现了这段代码,它实际上并没有“创建”用户:

def test_registration_signal(self):
        def receiver(sender, **kwargs):
            self.failUnless('user' in kwargs)
            self.assertEqual(kwargs['user'].username, 'bob')
            self.failUnless('request' in kwargs)
            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
            received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_registered.connect(receiver, sender=self.backend.__class__)

        self.backend.register(_mock_request(),
                              username='bob',
                              email='bob@example.com',
                              password1='secret')

        self.assertEqual(len(received_signals), 1)
        self.assertEqual(received_signals, [signals.user_registered])

但是,他为此“_mock_request”使用了自定义函数:

class _MockRequestClient(Client):
    def request(self, **request):
        environ = {
            'HTTP_COOKIE': self.cookies,
            'PATH_INFO': '/',
            'QUERY_STRING': '',
            'REMOTE_ADDR': '127.0.0.1',
            'REQUEST_METHOD': 'GET',
            'SCRIPT_NAME': '',
            'SERVER_NAME': 'testserver',
            'SERVER_PORT': '80',
            'SERVER_PROTOCOL': 'HTTP/1.1',
            'wsgi.version': (1,0),
            'wsgi.url_scheme': 'http',
            'wsgi.errors': self.errors,
            'wsgi.multiprocess':True,
            'wsgi.multithread': False,
            'wsgi.run_once': False,
            'wsgi.input': None,
            }
        environ.update(self.defaults)
        environ.update(request)
        request = WSGIRequest(environ)

        # We have to manually add a session since we'll be bypassing
        # the middleware chain.
        session_middleware = SessionMiddleware()
        session_middleware.process_request(request)
        return request


def _mock_request():
    return _MockRequestClient().request()

但是,它可能对我的需要来说太长了。我希望能够以某种方式“伪造”帐户创建。我在模拟和存根方面没有太多经验,所以任何帮助都可以。谢谢!

4

2 回答 2

2

这两种方法正在测试不同的东西:

  1. 您的测试用例测试模型层——它询问“如果我创建一个用户并保存它,配置文件记录会自动创建吗?”

    它不依赖于用户对象是如何创建的——通过管理视图、用户注册视图或管理命令——只要这个测试通过,你就知道任何通过 ORM 创建用户的方法将添加一个配置文件。

    它也不关心配置文件是如何创建的。它可能是通过预保存信号、保存后信号、覆盖的 save() 方法中的某些代码或魔法。只要创建了记录,测试就会通过。

  2. 您在 django-registration 中找到的代码正在测试视图层。它正在调用一个特定的视图函数,register向它传递三个 URL 参数,并询问“user_registered信号是否因为这个视图而被触发?”

    这个测试用例不看其他创建用户的方法;只是注册视图。它不关心任何其他创建用户的方法。

    它也不查看是否创建了配置文件。它只想知道信号是否被触发,而不管该信号在任何特定应用程序中的实际作用。

有什么不同?

您的代码是集成测试的一个很好的例子——“我是否将所有这些部分(模型、信号)按正确的顺序放在一起以便创建配置文件?” - 以及回归测试,以在未来向您发出信号,以确定您是否做了任何破坏用户配置文件创建的事情。

django-registration 代码是一个实际的单元测试。它非常小心地将视图代码隔离开来,在受控环境中调用它并提出一个简单的问题。

哪个更好?

在您的情况下,您可能不需要编写单元测试。(尽管可能对此有很多争论;这在某些方面实际上是宗教问题)您想要一种方法来验证您组合在一起的代码是否按照您的预期工作,以及您的测试是最好的方法。

不必担心实际创建用户——在测试运行期间,您在事务中执行所有操作,并且该事务在测试方法完成后立即回滚。它甚至可能不会击中磁盘。而且,正如@Platinum Azure 所提到的,无论如何它都在测试数据库中。

于 2012-09-28T05:33:27.583 回答
0

为什么要模拟用户创建?如果你运行 Django 的测试引擎,你正在测试一个测试数据库。只需调用视图或使用请求客户端工厂,然后让测试运行程序在完成后删除测试数据库。

于 2012-09-28T03:45:10.593 回答