Вы не можете сделать это с .load()
напрямую, так как он возвращает объект jQuery для цепочки, но если вы переключитесь на полный вызов $.ajax()
с помощью .html()
вы можете, например, так:
var xhr = $.ajax({
url: 'mypage.htm',
success: function(data) {
$("#myElement").html(data);
}
});
//if needed, abort the request later..
xhr.abort();
При этом используется метод .abort()
объекта XMLHttpRequest для прерывания загрузки.
I guess what you want is "parameterized tests".
I don't think unittest module supports this (unfortunately), but if I were adding this feature it would look something like this:
# Will run the test for all combinations of parameters
@RunTestWith(x=[0, 1, 2, 3], y=[-1, 0, 1])
def testMultiplication(self, x, y):
self.assertEqual(multiplication.multiply(x, y), x*y)
With the existing unittest module, a simple decorator like this won't be able to "replicate" the test multiple times, but I think this is doable using a combination of a decorator and a metaclass (metaclass should observe all 'test*' methods and replicate (under different auto-generated names) those that have a decorator applied).
Возможно что-то вроде:
def test_many(self):
for n in range(0,1000):
self.assertEqual(self.somevalue, n)
Напишите единый тестовый метод, который выполняет все ваши тесты и фиксирует все результаты, записывайте свои собственные диагностические сообщения в stderr и не пройдите тест, если какой-либо из его подтестов не прошел:
def test_with_multiple_parameters(self):
failed = False
for k in sorted(self.test_parameters.keys()):
if not self.my_test(self.test_parameters[k]):
print >> sys.stderr, "Test {0} failed.".format(k)
failed = True
self.assertFalse(failed)
Обратите внимание, что, конечно, имя my_test ()
не может начинаться с test
.
Если вы действительно хотите использовать несколько unitttest, вам понадобится несколько методов. Единственный способ добиться этого - создать своего рода код. Вы можете сделать это с помощью метаклассов или настроив класс после определения, в том числе (если вы используете Python 2.6) с помощью декоратора класса.
Вот решение, которое ищет специальные члены multitest и multitest_values и использует их для создания методов тестирования на лету. Не изящно, но делает примерно то, что вы хотите:
import unittest
import inspect
class SomeValue(object):
def __eq__(self, other):
return other in [1, 3, 4]
class ExampleTestCase(unittest.TestCase):
somevalue = SomeValue()
multitest_values = [1, 2, 3, 4]
def multitest(self, n):
self.assertEqual(self.somevalue, n)
multitest_gt_values = "ABCDEF"
def multitest_gt(self, c):
self.assertTrue(c > "B", c)
def add_test_cases(cls):
values = {}
functions = {}
# Find all the 'multitest*' functions and
# matching list of test values.
for key, value in inspect.getmembers(cls):
if key.startswith("multitest"):
if key.endswith("_values"):
values[key[:-7]] = value
else:
functions[key] = value
# Put them together to make a list of new test functions.
# One test function for each value
for key in functions:
if key in values:
function = functions[key]
for i, value in enumerate(values[key]):
def test_function(self, function=function, value=value):
function(self, value)
name ="test%s_%d" % (key[9:], i+1)
test_function.__name__ = name
setattr(cls, name, test_function)
add_test_cases(ExampleTestCase)
if __name__ == "__main__":
unittest.main()
Это результат, когда я его запустил
% python stackoverflow.py
.F..FF....
======================================================================
FAIL: test_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 13, in multitest
self.assertEqual(self.somevalue, n)
AssertionError: <__main__.SomeValue object at 0xd9870> != 2
======================================================================
FAIL: test_gt_1 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: A
======================================================================
FAIL: test_gt_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: B
----------------------------------------------------------------------
Ran 10 tests in 0.001s
FAILED (failures=3)
Вы можете сразу увидеть некоторые проблемы, возникающие при генерации кода. Откуда взялось "test_gt_1"? Я мог бы изменить имя на более длинное «test_multitest_gt_1», но тогда какой тест равен 1? Лучше было бы начать с _0 вместо _1, и, возможно, в вашем случае вы знаете, что значения могут использоваться как имя функции Python.
Мне не нравится этот подход. Я работал над кодовыми базами, которые автоматически генерировали методы тестирования (в одном случае с использованием метакласса), и обнаружил, что это было намного сложнее понять, чем было полезно. Когда тест не удался, было трудно определить источник сбоя, и было трудно придерживаться отладочного кода, чтобы выяснить причину сбоя.
(Отладка сбоев в примере, который я здесь написал, не такой, как сложно, как тот конкретный подход к метаклассу, с которым мне пришлось работать.)
Более ориентированный на данные подход мог бы быть более ясным, чем тот, который использовался в Эндрю Далке ответе :
"""Parametrized unit test.
Builds a single TestCase class which tests if its
`somevalue` method is equal to the numbers 1 through 4.
This is accomplished by
creating a list (`cases`)
of dictionaries which contain test specifications
and then feeding the list to a function which creates a test case class.
When run, the output shows that three of the four cases fail,
as expected:
>>> import sys
>>> from unittest import TextTestRunner
>>> run_tests(TextTestRunner(stream=sys.stdout, verbosity=9))
... # doctest: +ELLIPSIS
Test if self.somevalue equals 4 ... FAIL
Test if self.somevalue equals 1 ... FAIL
Test if self.somevalue equals 3 ... FAIL
Test if self.somevalue equals 2 ... ok
<BLANKLINE>
======================================================================
FAIL: Test if self.somevalue equals 4
----------------------------------------------------------------------
Traceback (most recent call last):
...
AssertionError: 2 != 4
<BLANKLINE>
======================================================================
FAIL: Test if self.somevalue equals 1
----------------------------------------------------------------------
Traceback (most recent call last):
...
AssertionError: 2 != 1
<BLANKLINE>
======================================================================
FAIL: Test if self.somevalue equals 3
----------------------------------------------------------------------
Traceback (most recent call last):
...
AssertionError: 2 != 3
<BLANKLINE>
----------------------------------------------------------------------
Ran 4 tests in ...s
<BLANKLINE>
FAILED (failures=3)
"""
from unittest import TestCase, TestSuite, defaultTestLoader
cases = [{'name': "somevalue_equals_one",
'doc': "Test if self.somevalue equals 1",
'value': 1},
{'name': "somevalue_equals_two",
'doc': "Test if self.somevalue equals 2",
'value': 2},
{'name': "somevalue_equals_three",
'doc': "Test if self.somevalue equals 3",
'value': 3},
{'name': "somevalue_equals_four",
'doc': "Test if self.somevalue equals 4",
'value': 4}]
class BaseTestCase(TestCase):
def setUp(self):
self.somevalue = 2
def test_n(self, n):
self.assertEqual(self.somevalue, n)
def make_parametrized_testcase(class_name, base_classes, test_method, cases):
def make_parametrized_test_method(name, value, doc=None):
def method(self):
return test_method(self, value)
method.__name__ = "test_" + name
method.__doc__ = doc
return (method.__name__, method)
test_methods = (make_parametrized_test_method(**case) for case in cases)
class_dict = dict(test_methods)
return type(class_name, base_classes, class_dict)
TestCase = make_parametrized_testcase('TestOneThroughFour',
(BaseTestCase,),
test_n,
cases)
def make_test_suite():
load = defaultTestLoader.loadTestsFromTestCase
return TestSuite(load(TestCase))
def run_tests(runner):
runner.run(make_test_suite())
if __name__ == '__main__':
from unittest import TextTestRunner
run_tests(TextTestRunner(verbosity=9))
Я не уверен, какое вуду участвует в определении порядка, в котором тесты проходят, но доктест у меня, по крайней мере, проходит стабильно.
Для более сложных ситуаций можно заменить элемент values
в словарях case
кортежем, содержащим список аргументов и словарь аргументов ключевого слова. Хотя в этот момент вы в основном кодируете lisp на python.