针对Zope和Plone的funkload扩展
项目描述
复杂的功能负载测试和基准测试
collective.funkload提供了一些对Funkload的扩展,Funkload是一个网络性能测试和报告工具。这些扩展提供了灵活而简单的方式来
运行多个测试场景的基准测试
针对多个配置运行这些基准测试
比较这些配置之间的差异
collective.funkload提供的所有控制台脚本都提供了一个“–help”选项,该选项记录了命令及其选项。
collective.funkload工作流程
1. 使用Python eggs(与unittest类似)开发测试场景
可以使用funkload测试记录器生成Funkload测试用例,然后将它们放入Python egg的“tests”包中,就像正常的unittest测试用例一样。
应该开发这些测试用例,以反映应用程序支持的所有使用模式。注意在根据使用场景(匿名访客、读取访问、写入访问等)分离测试与保持测试数量足够低以扫描结果之间保持平衡。
2. 基准测试基本配置
如果没有单一的基线,例如比较多个配置,那么这里的“基线”一词可能有些不准确。然而,重要的是要确立测试用例成功覆盖了使用场景。
使用collective.funkload提供的fl-run-bench,使用zope.testing.testrunner语义指定要运行的测试,并使用“–label”选项指定一个标签,表示基准测试(如果基线不适用,则指定其他标签)
$ fl-run-bench -s foo.loadtests --label=baseline Running zope.testing.testrunner.layer.UnitTests tests: Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds. ======================================================================== Benching FooTestCase.test_FooTest ======================================================================== ... Bench status: **SUCCESS** Ran # tests with 0 failures and 0 errors in # minutes #.### seconds. Tearing down left over layers: Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds.
使用“fl-build-report –html”从运行上述基准测试生成的XML构建HTML报告
$ fl-build-report --html FooTest-bench-YYYYMMDDThhmmss.xml Creating html report ...done: file:///.../test_ReadOnly-YYYYMMDDThhmmss-baseline/index.html
检查报告细节。如果测试用例没有充分覆盖应用程序支持的使用模式,请重复步骤1和2,直到测试用例提供足够的覆盖。
3. 基准测试其他配置
然后依次部署每个配置。此程序将由应用程序决定。例如,如果使用不同的buildout配置,则部署每个配置
$ ...
然后使用之前相同的fl-run-bench命令(或根据需要调整配置)并提供一个不同的“–label”选项,指定配置
$ fl-run-bench -s foo.loadtests --label=foo-setup Running zope.testing.testrunner.layer.UnitTests tests: Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds. ======================================================================== Benching FooTestCase.test_FooTest ======================================================================== ... Bench status: **SUCCESS** Ran # tests with 0 failures and 0 errors in # minutes #.### seconds. Tearing down left over layers: Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds.
为每个配置重复此步骤。
4. 构建HTML、差异报告和矩阵索引
使用带有“–x-label”和“–y-label”选项的“fl-build-label-reports”命令自动构建所有HTML报告、基于标签的差异报告以及HTML和差异报告的索引矩阵。该“fl-build-label-reports”脚本将根据标签使用默认标题和副标题,但可以使用“–title”和“–sub-title”选项指定。还可以使用stdin或“–input”选项包含任意文本或HTML
$ echo "When deciding which setup to use..." | \ fl-build-label-reports --x-label=baseline --y-label=foo-setup \ --y-label=bar-setup --title="Setup Comparison" --sub-title="Compare setups foo and bar against baseline" Creating html report ...done: file:///.../test_ReadOnly-YYYYMMDDThhmmss-baseline/index.html Creating html report ...done: file:///.../test_ReadOnly-YYYYMMDDThhmmss-foo-label/index.html Creating html report ...done: file:///.../test_ReadOnly-YYYYMMDDThhmmss-bar-label/index.html Creating diff report ...done: /.../diff_ReadOnly-YYYYMMDDT_hhmmss-foo-label_vs_hhmmss-baseline/index.html Creating diff report ...done: /.../diff_ReadOnly-YYYYMMDDT_hhmmss-bar-label_vs_hhmmss-baseline/index.html Creating report index ...done: file:///.../index.html
可以多次给出“–x-label”和“–y-label”选项,或者可以使用Python正则表达式创建一个MxN的差异报告矩阵。有关更多详细信息,请参阅“fl-build-label-reports –help”文档。
5. 使用矩阵索引检查结果
打开最后一条命令生成的index.html,以查看HTML报告和差异报告。
6. 根据更改重复
在您的应用程序或配置或测试新配置中做出更改时,重复步骤3和4。当重复步骤4时,通过运行“fl-build-label-reports”并根据需要调整“–x-label”和“–y-label”选项,将生成适用于新负载测试基准结果的适当HTML和差异报告,矩阵索引将更新。
fl-run-bench
FunKload安装的脚本通常需要在测试模块所在的目录下执行。虽然这对于使用FunKload录制器生成测试用例是合适的,但在运行负载测试基准时,这通常不是期望的行为。此外,基准运行程序的参数处理不允许使用zope.testing.testrunner语义来指定要基准测试的测试,例如,指定带有点路径的模块和包,正如在使用setuptools和eggs时经常这样做的那样。
为了适应这种使用模式,collective.funkload包提供了一层包装,用于处理Funkload基准运行程序中的点路径参数。具体来说,与传递*.py文件和TestCase.test_method参数不同,collective.funkload提供的“fl-bench-runner”支持使用“-s”,“-m”和“-t”来查找测试的zope.testing.testrunner语义。
>>> from collective.funkload import bench >>> bench.run(defaults, ( ... 'test.py -s foo -t test_foo ' ... '--cycles 1 --url http://bar.com').split()) t... Benching FooTestCase.test_foo... * Server: http://bar.com... * Cycles: [1]...
fl-build-label-reports
fl-build-label-reports脚本基于基准结果标签同时构建HTML(fl-build-report –html)和差异(fl-build-report –diff)报告。标签用于X轴和Y轴的比较,使用“–x-label”和“–y-label”选项选择。这些选项接受与zope.testing.testrunner –module和–test选项相同的正则表达式过滤器,并且像这些选项一样可以多次给出。
差异报告的方向或极性、哪个报告是参考哪个报告是挑战者,是通过排序涉及到的标签来确定的。这避免了如果将两个方向上的差异报告都包含在同一矩阵中可能出现的混淆,一个显示绿色,另一个显示红色。因此,标签应指定,以便它们的排序顺序将反映所需的差异极性。“–reverse”选项也可以用来仅反转极性的排序顺序而不影响轴的排序顺序。也就是说,当差异的极性应该是轴标签顺序的反向时,使用“–reverse”。
可以使用“–title”和“–sub-title”选项指定矩阵索引上渲染的标题和副标题。如果没有指定,将使用默认标题,并根据X轴和Y轴上的标签生成副标题。也可以使用stdin或使用“–input”选项包含任意文本或HTML。如果提供,它将在副标题下方和矩阵上方渲染。
在下面的示例中,已经运行了负载测试,以测量在Python 2.4、2.5和2.6下的读、写和添加性能。有三个不同的测试来测量读、写和添加性能。标签用于指定负载测试在哪个Python版本下运行。因此,可以使用fl-build-label-reports快速生成报告,这些报告可以用来评估各种Python版本对正在测试的应用程序可能产生的任何性能权衡。
从一些基准结果XML文件开始。
>>> import os >>> from collective.funkload import testing >>> testing.setUpReports(reports_dir) >>> sorted(os.listdir(reports_dir), reverse=True) ['write-bench-20081211T071242.xml', 'write-bench-20081211T071242.log', 'read-bench-20081211T071242.xml', 'read-bench-20081211T071242.log', 'read-bench-20081211T071241.xml', 'read-bench-20081211T071241.log', 'read-bench-20081210T071243.xml', 'read-bench-20081210T071243.log', 'read-bench-20081210T071241.xml', 'read-bench-20081210T071241.log', 'add-bench-20081211T071243.xml', 'add-bench-20081211T071243.log', 'add-bench-20081211T071242.xml', 'add-bench-20081211T071242.log']
这些基准结果覆盖多个测试,并具有多个标签。一些标签应用于多个测试的基准结果。
>>> import pprint >>> pprint.pprint(testing.listReports(reports_dir)) [(u'python-2.4', [(u'test_add', [(u'2008-12-11T07:12:43.000000', Bench(path='add-bench-20081211T071243.xml', diffs={}))]), (u'test_read', [(u'2008-12-11T07:12:42.000000', Bench(path='read-bench-20081211T071242.xml', diffs={})), (u'2008-12-10T07:12:43.000000', Bench(path='read-bench-20081210T071243.xml', diffs={}))])]), (u'python-2.5', [(u'test_read', [(u'2008-12-10T07:12:41.000000', Bench(path='read-bench-20081210T071241.xml', diffs={}))])]), (u'python-2.6', [(u'test_add', [(u'2008-12-11T07:12:42.000000', Bench(path='add-bench-20081211T071242.xml', diffs={}))]), (u'test_read', [(u'2008-12-11T07:12:41.000000', Bench(path='read-bench-20081211T071241.xml', diffs={}))])])]
当指定X轴或Y轴的标签时,为每个指定标签和具有可用基准结果的每个测试的最新基准结果XML文件生成HTML报告。然后生成X轴和Y轴之间的差异报告,形成一个报告网格。最后,生成一个index.html文件,提供对生成的报告的清晰和方便的访问。为python-2.4与python-2.6生成报告和比较。还指定了“–reverse”选项,以便差异极性将是轴标签顺序的反向。
>>> from collective.funkload import label >>> input_ = os.path.join(reports_dir, 'input.html') >>> open(input_, 'w').write('<a href="http://foo.com">foo</a>') >>> args = ( ... '-o %s --x-label python-2.4 --y-label !.*-2.5 --reverse' ... % reports_dir).split() + [ ... '--title', 'Python 2.6 vs Python 2.4', ... '--sub-title', 'Comparing Python versions', ... '--input', input_] >>> options, _ = label.parser.parse_args(args=args) >>> label.run(options) Creating html report ...done: .../reports/test_add-20081211T071242-python-2.6/index.html Creating html report ...done: .../reports/test_read-20081211T071241-python-2.6/index.html Creating html report ...done: .../reports/test_add-20081211T071243-python-2.4/index.html Creating diff report ...done: .../reports/diff_add-20081211T_071242-python-2.6_vs_071243-python-2.4/index.html Creating html report ...done: .../reports/test_read-20081211T071242-python-2.4/index.html Creating diff report ...done: .../reports/diff_read-20081211T_071241-python-2.6_vs_071242-python-2.4/index.html Creating report index ...done: .../reports/index.html '.../reports/index.html'
报告索引渲染一个表格,其中包含X轴和Y轴上HTML报告的链接,以及表格单元格中差分报告的链接。在这种情况下,X轴上只有一个HTML报告,Y轴上有四个报告。请注意,为了节省空间和避免重复,X轴的列标题中不包括报告链接。当只使用一个X轴标签时,即使差分报告单元格为空,也将其包含在Y轴中,以便包含每个测试的非差分测试报告的链接。
>>> print open(os.path.join(reports_dir, 'index.html')).read() <... <title>Python 2.6 vs Python 2.4</title>... <h1 class="title">Python 2.6 vs Python 2.4</h1> <h2 class="subtitle">Comparing Python versions</h2> <a href="http://foo.com">foo</a> <table class="docutils"> <thead> <tr class="field"> <th class="field-name" colspan="2"> </th> <th class="field-name" colspan="1"> Label </th> </tr> <tr class="field"> <th class="field-name">Label</th> <th class="field-name">Test</th> <th class="field-name">python-2.4</th> </tr> </thead> <tbody> <tr> <th class="field-name" rowspan="2">python-2.4</th> <th class="field-name"> <a href="test_add-20081211T071243-python-2.4/index.html"> <img alt="foo.sampletests.FooTestCase.test_add" src="test_add-20081211T071243-python-2.4/tests.png" height="120" width="120"/> <div>test_add</div> </a> </th> <td class="field-body"> </td> </tr> <tr> <th class="field-name"> <a href="test_read-20081211T071242-python-2.4/index.html"> <img alt="foo.sampletests.FooTestCase.test_read" src="test_read-20081211T071242-python-2.4/tests.png" height="120" width="120"/> <div>test_read</div> </a> </th> <td class="field-body"> </td> </tr> <tr> <th class="field-name" rowspan="2">python-2.6</th> <th class="field-name"> <a href="test_add-20081211T071242-python-2.6/index.html"> <img alt="foo.sampletests.FooTestCase.test_add" src="test_add-20081211T071242-python-2.6/tests.png" height="120" width="120"/> <div>test_add</div> </a> </th> <td class="field-body"> <a href="diff_add-20081211T_071242-python-2.6_vs_071243-python-2.4/index.html"> <img alt="diff of python-2.6 vs python-2.4 for test_add" src="diff_add-20081211T_071242-python-2.6_vs_071243-python-2.4/spps_diff.png" height="95" width="160"/> <div>python-2.6 vs python-2.4</div> </a> </td> </tr> <tr> <th class="field-name"> <a href="test_read-20081211T071241-python-2.6/index.html"> <img alt="foo.sampletests.FooTestCase.test_read" src="test_read-20081211T071241-python-2.6/tests.png" height="120" width="120"/> <div>test_read</div> </a> </th> <td class="field-body"> <a href="diff_read-20081211T_071241-python-2.6_vs_071242-python-2.4/index.html"> <img alt="diff of python-2.6 vs python-2.4 for test_read" src="diff_read-20081211T_071241-python-2.6_vs_071242-python-2.4/spps_diff.png" height="95" width="160"/> <div>python-2.6 vs python-2.4</div> </a> </td> </tr> </tbody> <tfooter> <tr class="field"> <th class="field-name">Label</th> <th class="field-name">Test</th> <th class="field-name">python-2.4</th> </tr> <tr class="field"> <th class="field-name" colspan="2"> </th> <th class="field-name" colspan="1"> Label </th> </tr> </tfooter> </table>...
如果没有指定X轴或Y轴的标签,则将选择X轴和Y轴的所有标签进行完整的NxN比较。只有当HTML报告和差分报告尚未生成时,才会生成它们。也就是说,将重用现有报告。没有标签的报告或结果将被忽略。由于HTML报告包含基准运行的XML结果文件,原始文件将被删除,任何相应的日志文件将被移动到HTML报告目录。
>>> open(input_, 'w').write('') >>> args = ('-o %s' % reports_dir).split()+['--input', input_] >>> options, _ = label.parser.parse_args(args=args) >>> label.run(options) Creating html report ...done: .../reports/test_read-20081210T071241-python-2.5/index.html Creating diff report ...done: .../reports/diff_read_20081211T071242-python-2.4_vs_20081210T071241-python-2.5/index.html Creating diff report ...done: .../reports/diff_read_20081210T071241-python-2.5_vs_20081211T071241-python-2.6/index.html Creating report index ...done: .../reports/index.html '.../reports/index.html'>>> pprint.pprint(sorted(os.listdir(reports_dir), reverse=True)) ['write-bench-20081211T071242.xml', 'write-bench-20081211T071242.log', 'test_read-20081211T071242-python-2.4', 'test_read-20081211T071241-python-2.6', 'test_read-20081210T071241-python-2.5', 'test_add-20081211T071243-python-2.4', 'test_add-20081211T071242-python-2.6', 'read-bench-20081210T071243.xml', 'read-bench-20081210T071243.log', 'input.html', 'index.html', 'diff_read_20081211T071242-python-2.4_vs_20081210T071241-python-2.5', 'diff_read_20081210T071241-python-2.5_vs_20081211T071241-python-2.6', 'diff_read-20081211T_071242-python-2.4_vs_071241-python-2.6', 'diff_read-20081211T_071241-python-2.6_vs_071242-python-2.4', 'diff_add-20081211T_071243-python-2.4_vs_071242-python-2.6', 'diff_add-20081211T_071242-python-2.6_vs_071243-python-2.4'] >>> os.path.isfile(os.path.join( ... reports_dir, 'test_read-20081211T071242-python-2.4', ... 'funkload.log')) True >>> os.path.isfile(os.path.join( ... reports_dir, 'test_read-20081211T071242-python-2.4', ... 'funkload.xml')) True
HTML报告索引将更新以反映新包含的结果和报告。
>>> print open(os.path.join(reports_dir, 'index.html')).read() <... <title> collective.funkload label matrix report </title>... <h1 class="title"> <a href="http://pypi.python.org/pypi/collective.funkload"> collective.funkload label matrix report </a> </h1> <h2 class="subtitle">python-2.4, python-2.5, python-2.6 vs python-2.4, python-2.5, python-2.6</h2> <table class="docutils"> <thead> <tr class="field"> <th class="field-name" colspan="2"> </th> <th class="field-name" colspan="3"> Label </th> </tr> <tr class="field"> <th class="field-name">Label</th> <th class="field-name">Test</th> <th class="field-name">python-2.4</th> <th class="field-name">python-2.5</th> <th class="field-name">python-2.6</th> </tr> </thead> <tbody> <tr> <th class="field-name" rowspan="2">python-2.4</th> <th class="field-name"> <a href="test_add-20081211T071243-python-2.4/index.html"> <img alt="foo.sampletests.FooTestCase.test_add" src="test_add-20081211T071243-python-2.4/tests.png" height="120" width="120"/> <div>test_add</div> </a> </th> <td class="field-body"> </td> <td class="field-body"> </td> <td class="field-body"> <a href="diff_add-20081211T_071243-python-2.4_vs_071242-python-2.6/index.html"> <img alt="diff of python-2.4 vs python-2.6 for test_add" src="diff_add-20081211T_071243-python-2.4_vs_071242-python-2.6/spps_diff.png" height="95" width="160"/> <div>python-2.4 vs python-2.6</div> </a> </td> </tr> <tr> <th class="field-name"> <a href="test_read-20081211T071242-python-2.4/index.html"> <img alt="foo.sampletests.FooTestCase.test_read" src="test_read-20081211T071242-python-2.4/tests.png" height="120" width="120"/> <div>test_read</div> </a> </th> <td class="field-body"> </td> <td class="field-body"> <a href="diff_read_20081211T071242-python-2.4_vs_20081210T071241-python-2.5/index.html"> <img alt="diff of python-2.4 vs python-2.5 for test_read" src="diff_read_20081211T071242-python-2.4_vs_20081210T071241-python-2.5/spps_diff.png" height="95" width="160"/> <div>python-2.4 vs python-2.5</div> </a> </td> <td class="field-body"> <a href="diff_read-20081211T_071242-python-2.4_vs_071241-python-2.6/index.html"> <img alt="diff of python-2.4 vs python-2.6 for test_read" src="diff_read-20081211T_071242-python-2.4_vs_071241-python-2.6/spps_diff.png" height="95" width="160"/> <div>python-2.4 vs python-2.6</div> </a> </td> </tr> <tr> <th class="field-name" rowspan="1">python-2.5</th> <th class="field-name"> <a href="test_read-20081210T071241-python-2.5/index.html"> <img alt="foo.sampletests.FooTestCase.test_read" src="test_read-20081210T071241-python-2.5/tests.png" height="120" width="120"/> <div>test_read</div> </a> </th> <td class="field-body"> <a href="diff_read_20081211T071242-python-2.4_vs_20081210T071241-python-2.5/index.html"> <img alt="diff of python-2.4 vs python-2.5 for test_read" src="diff_read_20081211T071242-python-2.4_vs_20081210T071241-python-2.5/spps_diff.png" height="95" width="160"/> <div>python-2.4 vs python-2.5</div> </a> </td> <td class="field-body"> </td> <td class="field-body"> <a href="diff_read_20081210T071241-python-2.5_vs_20081211T071241-python-2.6/index.html"> <img alt="diff of python-2.5 vs python-2.6 for test_read" src="diff_read_20081210T071241-python-2.5_vs_20081211T071241-python-2.6/spps_diff.png" height="95" width="160"/> <div>python-2.5 vs python-2.6</div> </a> </td> </tr> <tr> <th class="field-name" rowspan="2">python-2.6</th> <th class="field-name"> <a href="test_add-20081211T071242-python-2.6/index.html"> <img alt="foo.sampletests.FooTestCase.test_add" src="test_add-20081211T071242-python-2.6/tests.png" height="120" width="120"/> <div>test_add</div> </a> </th> <td class="field-body"> <a href="diff_add-20081211T_071243-python-2.4_vs_071242-python-2.6/index.html"> <img alt="diff of python-2.4 vs python-2.6 for test_add" src="diff_add-20081211T_071243-python-2.4_vs_071242-python-2.6/spps_diff.png" height="95" width="160"/> <div>python-2.4 vs python-2.6</div> </a> </td> <td class="field-body"> </td> <td class="field-body"> </td> </tr> <tr> <th class="field-name"> <a href="test_read-20081211T071241-python-2.6/index.html"> <img alt="foo.sampletests.FooTestCase.test_read" src="test_read-20081211T071241-python-2.6/tests.png" height="120" width="120"/> <div>test_read</div> </a> </th> <td class="field-body"> <a href="diff_read-20081211T_071242-python-2.4_vs_071241-python-2.6/index.html"> <img alt="diff of python-2.4 vs python-2.6 for test_read" src="diff_read-20081211T_071242-python-2.4_vs_071241-python-2.6/spps_diff.png" height="95" width="160"/> <div>python-2.4 vs python-2.6</div> </a> </td> <td class="field-body"> <a href="diff_read_20081210T071241-python-2.5_vs_20081211T071241-python-2.6/index.html"> <img alt="diff of python-2.5 vs python-2.6 for test_read" src="diff_read_20081210T071241-python-2.5_vs_20081211T071241-python-2.6/spps_diff.png" height="95" width="160"/> <div>python-2.5 vs python-2.6</div> </a> </td> <td class="field-body"> </td> </tr> </tbody> <tfooter> <tr class="field"> <th class="field-name">Label</th> <th class="field-name">Test</th> <th class="field-name">python-2.4</th> <th class="field-name">python-2.5</th> <th class="field-name">python-2.6</th> </tr> <tr class="field"> <th class="field-name" colspan="2"> </th> <th class="field-name" colspan="3"> Label </th> </tr> </tfooter> </table>...
“fl-list”脚本将打印出符合给定选项标准的标记XML基准结果文件、HTML报告目录和差分报告目录。
>>> from collective.funkload import report >>> options, _ = report.list_parser.parse_args( ... args=('-o %s --old' % reports_dir).split()) >>> list(report.run(**options.__dict__)) ['read-bench-20081210T071243.xml']
变更日志
0.4 (2014-06-20)
让flake8再次高兴 [giacomos]
添加创建dexterity内容类型的方 [giacomos]
修复label.py和tests.py与当前zope.testing不兼容的问题 [joka]
修复导入。zope.testing.testrunner现在位于zope.testrunner包中。 [nueces]
0.4 (2014-06-20)
添加新的TestCase类:PloneFLTestCase,包含两个辅助方法:plone_login和addContent。请参考collective.recipe.funkload的示例用法 [amleczko]
0.2.1 - 2010-04-16
修复recorder中的小错误 [amleczko]
0.2 - 2010-04-16
添加自定义的RecorderProgram版本,以使用我们自定义的Script模板 [amleczko]
0.1.1 - 2009-08-09
仅在调用bench时使用-m、-s、-t选项时运行funkload测试 [evilbungle]
0.1 - 2009-08-09
初始版本,主要是从主线分支到collective.recipe.funkload发布的快照
项目详情
collective.funkload-0.4.zip的散列值
算法 | 散列摘要 | |
---|---|---|
SHA256 | a277f7d2dd007e7868473ef916b96dc7e5150342f3cb8eaaa396f697f8b2e14a |
|
MD5 | 6fb59551a2ed66e4477aac80c5180bb1 |
|
BLAKE2b-256 | 3b5b6363d70407f771d670ec2a59359dcaed6fe4c6b825d422105c300ec7cf47 |