Skip to content

Commit

Permalink
[Front] 构建ReloadTestRunner (#5)
Browse files Browse the repository at this point in the history
* Add front runner.

* Solve Rebase Conflict.

* Move FIXTURE_DIRS into test_settings.

* Move logger from back's package into top package.

* Complete flush and loaddata func before front testting.

* Rename FrontTestRunner.

* Remove TAG_DB_MODIFY.

* Modify settings' place and update doc.

* Move log path into test_settings.

* Updata TODO.
  • Loading branch information
supplient committed Jun 7, 2019
1 parent 835c8cc commit 3292699
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 28 deletions.
4 changes: 0 additions & 4 deletions TODO

This file was deleted.

8 changes: 8 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
* 将所有subTest改成失败的话,直接整个TC都fail,因为我使用的所有的SubTest都只是表示的一个线性操作序列而已。
* 修改user photo相关的测试样例,劫持图床服务器。因为目前我没有劫持图床服务器,每次测试的时候都会向图床服务器发送一个真实的请求,这是不太合适的……会给人家的服务器带去虽然很小但确实存在的不必要的困扰。
* 现在前测试依然是使用正在跑的数据库当测试数据库,这并不安全。想办法解决这个问题,使得前测试也和后测试一样,在测试开始时创建一个专用的测试数据库。有两种可能可行的解:
* 研究怎么让正在跑的django server切换到我新建的test database
* 研究怎么在我开始测试的时候新建一个django服务器,并指定它在我新建的测试数据库上跑
* 在前测试点,构造usercase模拟一套用户的操作,并在此基础上实现并行测试。
* 并行测试:构建多个usercase,随机伪并发执行,检验是否运作正常。
* 易用性检查
29 changes: 23 additions & 6 deletions doc/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,10 @@


# 测试样例管理
我们使用了django提供的tag来管理需要特殊对待的测试样例,使得在测试时可以选取测试样例执行。目前使用的tag包括
* db_modify
* 用于前测试点,该测试样例会修改数据库,每次使用前需要刷新数据库,重新加载测试数据库。
* 待废弃
我们使用了django提供的tag来管理需要特殊对待的测试样例,使得在测试时可以选取测试样例执行。目前使用的tag包括:
*

在我的不断努力下,已经没有需要特殊对待的测试样例了。


# bug管理
Expand All @@ -335,17 +335,34 @@
1. 若一切正常,关闭issue。
2. 若出现问题,继续讨论解决。

# 测试数据库
# 测试数据
使用`test/fixture.json`作为前测试点测试数据,`test/back_fixture.json`作为后测试点测试数据。

通过以下指令导出
fixture可通过以下指令(back_fixtrue.json也是类似的指令)从数据库中导出

python test/test_manage.py dumpdata -e contenttypes -e admin -e auth.Permission --natural-foreign --indent=2 > test/fixture.json

通过以下指令加载(注意是追加式的加载):

python test/test_manage.py loaddata test/fixture.json

## 后测试点测试时的测试数据载入
该工作完全交由django进行,我们在BackBasicTestCase中指定类属性fixtures,随后每次执行后测试时,django会自动根据该fixture创建一个测试数据库,随后都在该测试数据库上进行测试,直到测试结束,测试数据库自动销毁。

一般地,可以通过执行该命令进行后测试:
`python test/test_manage.py test test/back`

## 前测试点测试时的测试数据载入
这部分工作比较麻烦。因为前测试点需要一个具有固定端口的django服务器,而django自动创建的测试服务器是具有随机端口的。所以我们只能使用在测试开始前就启动的具有固定端口的django服务器的数据库作为测试数据库。

为此我们构建了一个专门的TestRunner: ReloadTestRunner。该runner会在每次测试开始前自动地刷新数据库,并载入测试数据到数据库中。原理是简单地调用django内核中的flush和loaddata Command。

一般地,可以通过执行该命令进行前测试:
`python test/test_manage.py test test/front --testrunner=test.reload_runner.ReloadTestRunner`

可以发现,和后测试的差别仅在于指定了test runner。事实上,后测试也可以指定这么一条,反正也没啥影响。


# 测试环境下的秘钥管理
因为我们的后端采用的方法是使用环境变量保存秘钥,然后在加载settings时读取秘钥,所以我们需要为测试环境也创造这些秘钥。

Expand Down
2 changes: 0 additions & 2 deletions front/template/front_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

from test.front.cover_saver import cover_saver

TAG_DB_MODIFY = "db_modify"

class FrontBasicTC(TestCase):
@classmethod
def setUpClass(cls):
Expand Down
2 changes: 1 addition & 1 deletion front/template/front_content_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from test.front.page_objects import *
from test.front.user_actions import *
from .front_basic import FrontBasicTC, TAG_DB_MODIFY
from .front_basic import FrontBasicTC

class FrontContentCheckTC(FrontBasicTC):
def test_detail_course(self):
Expand Down
11 changes: 1 addition & 10 deletions front/template/front_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from test.front.page_objects import *
from test.front.user_actions import *
from test.front.util import rs
from .front_basic import FrontBasicTC, TAG_DB_MODIFY
from .front_basic import FrontBasicTC


class FrontFuncLogInTC(FrontBasicTC):
Expand Down Expand Up @@ -40,8 +40,6 @@ def test_person(self):
self.assertEqual(form["gender"], "M")
self.assertEqual(form["intro"], "mingming")

@skip
@tag(TAG_DB_MODIFY)
def test_comment(self):
test_words = "test_login_comment_is_mine"

Expand Down Expand Up @@ -86,7 +84,6 @@ def test_comment(self):


class FrontFuncRegistTC(FrontBasicTC):
@tag(TAG_DB_MODIFY)
def test_regist_exist_user(self):
page = HomePage(self.driver, self.domain)
page = page.goRegistPage()
Expand All @@ -100,7 +97,6 @@ def test_regist_exist_user(self):
rs(min=3)
page.checkIsSelf()

@tag(TAG_DB_MODIFY)
def test_regist_not_exist_user(self):
test_name = "__TRNEU__"
test_pw = "abc123!@#"
Expand Down Expand Up @@ -316,7 +312,6 @@ def test_search_page(self):
page=page,
)

@skip
def test_detail_page(self):
page = HomePage(self.driver, self.domain)
page = page.search("rbq")
Expand All @@ -328,7 +323,6 @@ def test_detail_page(self):


class FrontFuncPersonInfoTC(FrontBasicTC):
@tag(TAG_DB_MODIFY)
def test_modify_form(self):
page = HomePage(self.driver, self.domain)
with LogStatus(page, "rbq", "rbq") as page:
Expand All @@ -349,7 +343,6 @@ def test_modify_form(self):
page.submit()
self.assertDictEntry(page.getForm(), old_form)

@tag(TAG_DB_MODIFY)
def test_modify_photo(self):
page = HomePage(self.driver, self.domain)
with LogStatus(page, "rbq", "rbq") as page:
Expand Down Expand Up @@ -381,7 +374,6 @@ def checkRateState(self, page:DetailPage, index:int, is_up:bool, is_down:bool, r
self.assertEquals(page.isThumbDown(index), is_down)
self.assertEquals(page.getCommentRateRank(index), rate_rank)

@tag(TAG_DB_MODIFY)
def test_rate_comment(self):
'''This testcase takes very long time, at least 20s'''
page = HomePage(self.driver, self.domain)
Expand Down Expand Up @@ -499,7 +491,6 @@ def test_check_exist(self):
"content": "那你很棒棒哦",
})

@tag(TAG_DB_MODIFY)
def test_create_new(self):
page = HomePage(self.driver, self.domain)
with LogStatus(page, "rbq", "rbq") as page:
Expand Down
5 changes: 1 addition & 4 deletions front/template/front_go_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from test.front.page_objects import *
from test.front.user_actions import *
from .front_basic import FrontBasicTC, TAG_DB_MODIFY
from .front_basic import FrontBasicTC

class FrontHomeGoLogicTC(FrontBasicTC):
def createInitPage(self):
Expand Down Expand Up @@ -46,7 +46,6 @@ def createInitPage(self):
searchpage.checkIsSelf()
return searchpage

@tag("kkk")
def test_home(self):
searchpage = self.createInitPage()
homepage = searchpage.goHomePage()
Expand Down Expand Up @@ -145,7 +144,6 @@ def test_person(self):
page = page.goPersonPage()
page.checkIsSelf()

@tag(TAG_DB_MODIFY)
def test_detail(self):
page = HomePage(self.driver, self.domain)
with LogStatus(page, "rbq", "rbq") as page:
Expand All @@ -171,7 +169,6 @@ def test_login_normal(self):
page = page.goLoginPage()
page.checkIsSelf()

@tag(TAG_DB_MODIFY)
def test_login_submit(self):
page = self.createInitPage()
page.fillForm(
Expand Down
38 changes: 38 additions & 0 deletions reload_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env python
import os

import test_settings
from .rmc_test_logger import log
from django.conf import settings
from django.test.runner import DiscoverRunner
from django.core.management.commands import loaddata, flush

class ReloadTestRunner(DiscoverRunner):
'''This TestRunner will flush and load database before testting.'''

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

db_name = settings.DATABASES["default"]["NAME"]
if test_settings.DATABASES["default"]["NAME"] != db_name:
raise Exception("Please test from test_manage.py, because of an independent test database needed for front testing.")

# Flush test database
log.info("Start flushing database [{0}]...".format(db_name))
flush_cmd = flush.Command()
flush_cmd.run_from_argv([
"test/test_manage.py",
"flush",
"--noinput",
])
log.info("Finished flushing!")

# Load fixture
log.info("Start installing fixture on database [{}] from [{}]...".format(db_name, test_settings.FRONT_FIXTURE))
load_cmd = loaddata.Command()
load_cmd.run_from_argv([
"test/test_manage.py",
"loaddata",
test_settings.FRONT_FIXTURE,
])
log.info("Finished installing.")
3 changes: 2 additions & 1 deletion back/rmc_test_logger.py → rmc_test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
import logging
import sys
import os
from .test_settings import LOG_PATH

log = logging.getLogger("rateMyCourse_test")
log.setLevel(logging.DEBUG)

formatter = logging.Formatter("[%(levelname)s] %(message)s")

file_handler = logging.FileHandler("test/test.log", "wt")
file_handler = logging.FileHandler(LOG_PATH, "wt")
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
log.addHandler(file_handler)
Expand Down
20 changes: 20 additions & 0 deletions test_settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from flamenco.settings import *

FIXTURE_DIRS = [
"test",
]

INSTALLED_APPS.append(
'werkzeug_debugger_runserver',
)
Expand All @@ -13,3 +17,19 @@
CSRF_TRUSTED_ORIGINS = [
"ratemycourse.tk"
]

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'test_db.sqlite3'),
}
}


###########################################
# Following are our settings, not django's
###########################################

FRONT_FIXTURE = "test/fixture.json"

LOG_PATH = "test/test.log"

0 comments on commit 3292699

Please sign in to comment.