2016-06-30 3 views
4

단위 테스트 및 장고 트랜잭션 관리 방법에 문제가 있습니다. 내가 가진 내 테스트에서TransactionTestCase 및 pytest로 테스트가 실패합니다

def send(): 
    autocommit = transaction.set_autocommit(False) 
    try: 
     # stuff 
    finally: 
     transaction.rollback() 
     transaction.set_autocommit(autocommit) 

:

class MyTest(TransactionTestCase): 
    def test_send(self): 
     send() 

오전 데 문제가 내 test_send 내 다른 성공적으로하지만 80 %를 전달하는 내 코드에서

나는 기능이 테스트. 을 나는 단지 MyApp를 내 테스트를 실행할 때 일을 더 명확하게하려면

다른 시험의 트랜잭션이 BTW 내 테스트

편집을 실행하는 데 py.test를 사용하고

실패하는 것 같다 .test.test_module.py 잘 실행되고 3 가지 테스트가 모두 통과되지만 대부분의 테스트를 모두 실패하면 테스트 애플리케이션을 생성하려고 시도합니다

또한 모든 테스트는 django의 기본 테스트 러너

EDIT2 : 여기 이 문제를 테스트하는 최소한의 예는 다음과 같습니다 염두에

class ManagementTestCase(TransactionTestCase): 

    def test_transfer_ubl(self, MockExact): 
     pass 

class TestTestCase(TestCase): 

    def test_1_user(self): 
     get_user_model().objects.get(username="admin") 
     self.assertEqual(get_user_model().objects.all().count(), 1) 

베어는 "관리자"사용자를 추가하는 datamigration이

을합니다 (ManagmentTestCase 전에 실행할 때 TestTestCase 혼자가 아니라 성공)

자동 커밋은 아무 관계가없는 것처럼 보입니다.

+0

이 send() 메소드의 출처는 무엇입니까? send()를 호출 한 후에 실패한 테스트의 예를 게시하십시오. – e4c5

+0

send 메소드를 작성했습니다. 다른 객체가 격리되어있는 객체를 계산할 때 실패합니다. – maazza

+0

내 의견이 명확하지 않으면 죄송합니다. send 메소드는 뷰의 일부입니까? 테스트 코드의 일부입니까? 또한 함께 실행될 때 실패한 테스트 샘플을 추가하십시오. – e4c5

답변

4

TestCase 클래스는 두 개의 원자 블록 안에 테스트를 래핑합니다. 따라서 TestCase에서 상속하는 경우 transaction.set_autocommit() 또는 transaction.rollback()을 사용할 수 없습니다.

특정 데이터베이스 트랜잭션 동작을 테스트하는 경우에는 TransactionTestCase을 사용해야합니다.

+0

나는 그것을했다. 그러나 그것은 나의 다른 테스트의 대부분을 깬다 – maazza

+0

테스트 클래스를 2 개의 클래스로 나눈다. 'test_send' 메쏘드에'TransactionTestCase'를 쓰고 다른 것들에는'TestCase'를 사용하십시오. – Alasdair

+0

나는 그것을했다, 나는 300 개 이상의 테스트를 가진다. – maazza

3

autocommit = transaction.set_autocommit(False) (send) 기능이 잘못되었습니다. 트랜잭션을 사용하지 않도록 설정하는 것은 테스트 목적으로 여기에서 수행되지만, 경험적 규칙은 테스트 논리를 코드 외부에 유지하는 것입니다.

@Alasdair가 지적한 것처럼 django docs은 "Django의 TestCase 클래스는 성능상의 이유로 각 테스트를 트랜잭션으로 래핑합니다."

당신이 특정 데이터베이스 트랜잭션 로직을 테스트하고 있는지 여부는 명확하지 않습니다. 그렇다면 @Alasdair의 답변은 TransactionTestCase을 사용하는 것입니다.

그렇지 않으면 send 기능 내부의 stuff 주위에서 트랜잭션 컨텍스트 스위치를 제거하는 데 도움이됩니다.

테스트 주자로 pytest을 언급 했으므로 pytest를 사용하는 것이 좋습니다. Pytest-django plugin에는 markers을 사용하여 트랜잭션이 필요하도록 테스트 중 일부를 선택적으로 설정하는 등의 유용한 기능이 있습니다.플러그인을 설치하는 것은 너무 많은 경우

pytest.mark.django_db(transaction=False) 

, 당신은 당신의 자신의 transaction manage 고정 롤 수 있습니다.

@pytest.fixture 
    def no_transaction(request): 
     autocommit = transaction.set_autocommit(False) 
     def rollback(): 
      transaction.rollback() 
      transaction.set_autocommit(True) 
     request.addfinalizer(rollback) 

처럼 test_send 다음 no_transaction 고정이 필요합니다.

def test_send(no_transaction): 
    send() 
+0

autocommit = False + transaction.rollback을 사용합니다. 왜냐하면 send() 함수는 모델을 db에 저장하고 싶지 않기 때문에 DB를 수정하지 않고 테스트 로직과 아무 관계가 없기 때문에 pytest를 사용하려고했습니다. .mark를 성공하지 못하면 다시 시도 할 것입니다 – maazza

+0

pytest.mark.django_db (transaction = False)를 사용했지만 나중에 테스트 중에 데이터베이스가 비어있는 것으로 보이므로 나중에 테스트 할 때 다른 오류가 발생합니다 – maazza

+0

완전히 새로운 정리를 얻습니다. 각각의 테스트에 대한 예정된 데이터베이스. 만약 이것이 원하지 않는다면, http://pytest-django.readthedocs.io/en/latest/database.html#django-db-keepdb의''keepdb'' 옵션을 명시 적으로 사용할 수 있습니다. – Meitham

관련 문제