我使用Flask和WTForms以及标准和自定义表单验证器编写了一个相对简单的Web应用程序。我现在正在尝试学习Python测试。我已经编写了以下tests.py文件,该文件可与unittest正常工作,但具有冗余性。有没有更好,更有效,更Pythonic(DNRY)的方法来做到这一点?我看过一些pytest教程,想知道固定装置是否会有所帮助,但我不太了解它们。而且我认为使用unittest可以使用更多的Python方法。看来我需要一种可以将不同的dict参数传递给的方法,但是我不知道该怎么做。
10-27 22:05:47.881 22671-22767/com.smilebooth.easyshare E/AndroidRuntime: FATAL EXCEPTION: android_2
Process: com.smilebooth.easyshare, PID: 22671
java.lang.NoSuchMethodError: No static method catching(Lcom/google/common/util/concurrent/ListenableFuture;Ljava/lang/Class;Lcom/google/common/base/Function;)Lcom/google/common/util/concurrent/ListenableFuture; in class Lcom/google/common/util/concurrent/Futures; or its super classes (declaration of 'com.google.common.util.concurrent.Futures' appears in /data/app/com.smilebooth.easyshare-_OaEo0xawrKXOX90QnGu-Q==/split_lib_dependencies_apk.apk!classes2.dex)
at com.google.api.core.ApiFutures.catching(ApiFutures.java:77)
at com.google.photos.library.v1.upload.PhotosLibraryUploadUnaryCallable.futureCall(PhotosLibraryUploadUnaryCallable.java:50)
at com.google.photos.library.v1.upload.PhotosLibraryUploadUnaryCallable.futureCall(PhotosLibraryUploadUnaryCallable.java:31)
at com.google.api.gax.rpc.UnaryCallable.futureCall(UnaryCallable.java:87)
at com.google.api.gax.rpc.UnaryCallable.call(UnaryCallable.java:112)
at com.google.photos.library.v1.PhotosLibraryClient.uploadMediaItem(PhotosLibraryClient.java:125)
at com.smilebooth.data.repository.ShareDataRepository.uploadPhotoContent(ShareDataRepository.kt:201)
at com.smilebooth.data.repository.ShareDataRepository.share(ShareDataRepository.kt:104)
at com.smilebooth.domain.usecase.ShareUseCase$buildUseCaseObservable$1.subscribe(ShareUseCase.kt:21)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
at io.reactivex.Observable.subscribe(Observable.java:12090)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run(ExecutorScheduler.java:260)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
答案 0 :(得分:2)
我建议您创建一个自定义断言方法(assertExtensiveFlightSearchGivesError(self, data, expected_error_message)
)来删除某些重复项:
class FlaskTestCase(unittest.TestCase):
def assertExtensiveFlightSearchGivesError(self, data, expected_error_message):
response = test_client.post("/flight_search/extensive", data=data)
self.assertEqual(4xx, response.status_code)
self.assertIn(expected_error_message, response.data, "extensive flight search did not contain expected error message")
def test_city_code(self):
self.assertExtensiveFlightSearchGivesError(
{'origin': 'xxx'},
b'That does not appear to be a valid city code'
)
def test_code_pairs(self):
self.assertExtensiveFlightSearchGivesError(
{'origin': "HFD", 'destination': "CAS"},
b'This origin-destination pair is not in searchable cache'
)
# ... and so on
您还可以将所有测试用例收集在一起并使用.subTest()
:
TEST_CASES = [
({'origin': 'xxx'}, b'That does not appear to be a valid city code'),
({'origin': "HFD", 'destination': "CAS"}, b'This origin-destination pair is not in searchable cache')
]
class FlaskTestCase2(unittest.TestCase):
def assertExtensiveFlightSearchGivesError(self, data, expected_error_message):
response = test_client.post("/flight_search/extensive", data=data)
self.assertEqual(4xx, response.status_code)
self.assertIn(expected_error_message, response.data, "extensive flight search did not contain expected error message")
def test_all_error_cases(self):
for data, expected_error_message in TEST_CASES:
with self.subTest():
self.assertExtensiveFlightSearchGivesError(data, expected_error_message)
但是,在您的情况下,IMO最顶层的代码示例更加清晰。