source

assertEquals() 매개 변수가 순서(예상, 실제)인 이유는 무엇입니까?

factcode 2023. 7. 28. 22:57
반응형

assertEquals() 매개 변수가 순서(예상, 실제)인 이유는 무엇입니까?

왜 그렇게 많거나 유사한 함수들이 기대값을 첫 번째 매개변수로, 실제 매개변수를 두 번째 매개변수로 사용합니까?제가 보기에 이것은 직관에 어긋나는 것 같은데, 이 이례적인 주문에는 특별한 이유가 있나요?

Junit의 공동 제작자인 Kent Beck의 대답은 다음과 같습니다(이 컨벤션은 아마도 그의 이전 SUunit이 포함되지 않은 것으로 보이기 때문에 이 컨벤션이 기원일 수 있습니다).

동일한 주장 집합을 한 줄로 정렬합니다.먼저 예상하는 것이 그들을 더 잘 읽게 합니다.

제 답변의 초기 버전에서, 저는 이것을 이해하지 못했다고 말했습니다.다음은 제가 시험에서 자주 보는 것입니다.

assertEquals(12345, user.getId());
assertEquals("kent", user.getUsername());
assertEquals("Kent Beck", user.getName());

저는 이것이 먼저 실제 값과 함께 더 잘 읽힐 것이라고 생각합니다.이를 통해 더 많은 반복적인 보일러 플레이트를 결합하여 테스트할 값이 누구인지 메서드 호출을 정렬합니다.

assertEquals(user.getId(), 12345);
assertEquals(user.getUsername(), "kent");
assertEquals(user.getName(), "Kent Beck");

(그리고 제가 이 순서를 선호하는 다른 이유도 있지만, 왜 반대인지에 대한 이 질문의 목적으로, 켄트의 추론이 정답인 것 같습니다.)

그러나 Bob Stein은 아래에 "먼저 예상한" 몇 가지 사항을 제안하는 코멘트(이와 거의 유사)를 가지고 있습니다.주요 아이디어는 예상 값이 일반적으로 더 짧다는 것입니다. 종종 복잡한 메서드 호출보다는 리터럴 또는 변수/필드입니다.그 결과:

assertEquals(12345,       user.getId());
assertEquals("kent",      user.getUsername());
assertEquals("Kent Beck", user.getName());

고마워, 밥!

작가들이 당신의 직관과 일치할 확률이 50%였기 때문입니다.

다른 과부하 때문에

assertWhatever(explanation, expected, actual)

그리고 여러분이 알고 있는 것의 일부인 설명은 예상되는 것과 일치합니다. 여러분이 알고 있는 것은 실제와 반대되는 것입니다. 여러분이 코드를 작성할 때는 알지 못합니다.

.assertEqual()인간 독자를 위한 코드 데모입니다.

단순 함수 호출은 왼쪽에 반환 값을 표시하고 오른쪽에 호출을 표시합니다.

    y = f(x)

이 규칙에 따라 기능의 자가 테스트 데모는 다음과 같습니다.

    assertEqual(y, f(x))

순서는 (예상, 실제)입니다.

왼쪽에는 문자 그대로 예상되는 반환 값이 있는 sum() 함수와 오른쪽에는 실제 반환 값을 계산하는 함수 호출의 데모가 있습니다.

    assertEqual(15, sum((1,2,3,4,5)))

마찬가지로, 여기 한 표현의 데모가 있습니다.또한 다음과 같은 (예상, 실제) 순서로 자연스럽습니다.

    assertEqual(4, 2 + 2)

또 다른 이유는 스타일입니다.항목을 정렬하는 것을 좋아하는 경우 기대되는 모수가 더 짧은 경향이 있기 때문에 왼쪽에 더 좋습니다.

assertEqual(42, 2 * 3 * 7)
assertEqual(42, (1 << 1) + (1 << 3) + (1 << 5))
assertEqual(42, int('110', int('110', 2)))

저는 이것이 @Chris Povirk가 Kent Beck가 의미하는 "예상되는 첫 번째가 그들을 더 잘 읽게 한다"는 것에 대해 제기한 미스터리를 해결한다고 의심합니다.

Andrew WeimholtGanesh Parameswaran에게 이 공식들에 대해 감사합니다.

이것은 매우 흥미로운 주제이며, 여기에서도 매우 교육적인 답변들이 많이 있습니다!다음은 제가 그들에게서 배운 것입니다.

  1. 직관적인/반직관적인 것은 주관적인 것으로 간주될 수 있으므로, 원래 어떤 순서로 정의되었든 간에, 아마도 우리 중 50%는 행복하지 않을 것입니다.

  2. 개인적으로 나는 그것이 다음과 같이 설계되었으면 좋았을 것입니다.assertEqual(actual, expected)왜냐하면, 사이의 개념적 유사성을 고려할 때.assert그리고.if를 들어, 저는 그것이 의 규범을 따르기를 바랍니다.

    (PS: 실수로 하나를 놓치는 것을 방지하기 위해 "역순"으로 if 문을 작성하도록 유도하는 다양한 의견이 있는 것은 사실입니다.=하지만 그 스타일은 C/C++ 세계에서도 일반적인 스타일과는 거리가 멀었습니다.그리고 만약 당신이 파이썬 코드를 쓰고 있다면, 당신은 애초에 그 끔찍한 오타에 취약하지 않습니다, 왜냐하면if a = 1Python에서는 사용할 수 없습니다.)

  3. 해야 할 실질적이고 설득력 있는 이유assertEqual(expect, actual)해당 언어의 유니트 테스트 라이브러리가 이미 해당 순서를 따라 읽을 수 있는 오류 메시지를 생성했을 가능성이 높다는 것입니다.예를 들어, Python에서 다음과 같은 경우assertEqual(expected_dictionary, actual_dictionary)unittest는 당신이 할 때와 마찬가지로, 접두사와 함께 누락된 키를 실제로 표시하고 접두사와 함께 추가 키를 표시할 입니다.git diff old_branch new_branch.

    직관적이든 아니든, 이것이 지속해야 할 가장 설득력 있는 이유입니다.assertEqual(expected, actual)순서. 만약 여러분이 그것을 좋아하지 않는다면, 여전히 그것을 받아들이는 것이 좋을 것입니다. 왜냐하면 "실용성이 순수성을 이기거든요."

  4. 마지막으로, 만약 당신이 순서를 기억하는 것을 도울 방법이 필요하다면, 대답은 비교됩니다.assertEqual(expected_result, actual_calculation) 순서 할당명순로에result = calculate(...)그것은 사실상의 행동을 기억하는 좋은 방법이 될 수 있지만, 그것은 논쟁의 여지가 없는 그 순서의 추론이 더 직관적인 것은 아닙니다.

자, 여자기있습다니. ㅠㅠㅠassertEqual(expect, actual)!

일관성이 1위라는 공감대에는 동의하지만, 이 질문을 평가할 때 사전을 비교하는 행동이 도움이 될 수 있습니다.

diff에 "+"가 표시되면 "테스트 중인 절차에 추가되었습니다."라고 읽습니다.다시 개인 기본 설정이 적용됩니다.

참고: 알파벳 키를 사용하고 사전을 더 길게 만들어 예제의 명확성을 위해 중간 키만 변경할 수 있도록 했습니다.다른 시나리오에서는 난독화된 디프가 더 많이 표시됩니다.또한 assertEqual은 >=2.7 및 >=3.1에서 assertDicEqual을 사용합니다.

파일 exl.py

from unittest import TestCase


class DictionaryTest(TestCase):

    def test_assert_order(self):
        self.assertEqual(
            {
                'a_first_key': 'value',
                'key_number_2': 'value',
                'z_last_key': 'value',
                'first_not_second': 'value',
            },
            {
                'a_first_key': 'value',
                'key_number_2': 'value',
                'z_last_key': 'value',
                'second_not_first': 'value',
            }
        )

실행:

python -m unittest exl

출력:

F
======================================================================
FAIL: test_assert_order (exl.DictionaryTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "exl.py", line 18, in test_assert_order
    'second_not_first': 'value',
AssertionError: {'a_first_key': 'value', 'z_last_key': 'value', 'key_number_2': 'value', 'first_ [truncated]... != {'a_first_key': 'value', 'z_last_key': 'value', 'key_number_2': 'value', 'second [truncated]...
  {'a_first_key': 'value',
-  'first_not_second': 'value',
   'key_number_2': 'value',
+  'second_not_first': 'value',
   'z_last_key': 'value'}

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

xUnit 테스트 규칙은 예상/실제입니다.그래서 많은 사람들에게 그것은 자연스러운 질서입니다. 왜냐하면 그들은 그것을 배웠기 때문입니다.

흥미롭게도, xUnit 프레임워크에 대한 관례에서 벗어난 qunit은 실제/예상치에 해당합니다.적어도 JavaScript를 사용하면 이전 함수를 캡슐화하는 새 함수를 만들고 원래 변수를 할당할 수 있습니다.

var qunitEquals = equals;
equals = function(expected, actual, message) {
    qunitEquals(actual, expected, message);
};

첫 번째 매개 변수의 이름을 지정하는 문서first 두 매개 변수는 " 고두번째매개변수그리수변매▁and"입니다.second:

assertEqual(first, second, msg=None)

을 시험해 .first그리고.second실패합니다.값이 동일하게 비교되지 않으면 검정이 실패합니다.

그러나 문서에 나와 있는 대부분의 예제를 보면 수신된 값이 첫 번째이고 예상 값이 두 번째입니다(질문 게시물의 주장과 반대).

self.assertEqual(self.widget.size(), (50,50), 'incorrect default size')

저는 컨벤션이 그서저그대가회는라고 말하고 .assertEqual(got, expected)그리고 그 반대는 아닙니다!

어느 쪽이든, 당신의 테스트는 여전히 작동할 것입니다.

저는 이 대답을 아직 보지 못해서 조금 놀랐습니다. 왜냐하면 그것은 항상 제게 가장 가능성 있는 설명처럼 보였기 때문입니다.

당신이 가지고 있지 않았다고 상상해 보세요. assertEquals하지만 그냥assert당신은 시험을 어떻게 쓰시겠습니까?다음과 같이 쓸 수 있습니다.

assert(actual == expected)

개체가 단지 개체일 뿐이기 의존적일 것입니다▁the▁use그,▁but▁can'▁reliably-다t니습없수▁you▁won그안▁they정▁equival▁languageand적▁the러),,▁perhaps▁object,▁ones▁cases▁so▁many▁just▁in▁samedependentent▁is'▁(할나사용으▁(로==사용자의 의도를 표현하는 연산자입니다.다음으로 전환합니다.

assert(actual.equals(expected))

그리고 당분간은 괜찮아요.하지만 버그를 도입하면 결과(실제)가 무효가 되기 때문에 테스트가 실패합니다.하지만 시험은 당신이 기대하는 방식으로 실패하지 않습니다. 대신, 당신은 심지어 호출할 수도 없습니다.actual.equals당신은 메소드를 호출할 객체조차 없기 때문입니다!테스트 자체가 취약하기 때문에 테스트 코드가 예외로 표시됩니다.

그러나 예상 개체는 null이 아닙니다.

이것에 , 은 OO언어로 일하는 것과 같은 모든 방법 습관을 있습니다.if ("foo".equals(myString))그것은 여전히 안전한 경우입니다.myStringnull입니다(그 반대는 안전하지 않지만).

그래서 글쓰기의 가장 좋은 습관은 다음과 같습니다.

assert(expected.equals(actual))

실제가 잘못되면 실패하고, null인 경우에도 실패합니다.

몇 나면 단위 합니다.assertEquals입니다 :) 법방, 당에게자느게껴주질순장서단다하는니나입 :)

제가 들은 설명은 테스트 주도 개발(TDD)에서 나온다는 것입니다.

테스트 기반 개발에서는 테스트부터 시작하여 코드를 작성합니다.

예상을 작성하고 그것을 생성해야 하는 코드를 호출함으로써 주장을 시작하는 것은 그러한 사고방식의 미니 버전입니다.

물론, 이것은 사람들이 하는 이야기일 수도 있습니다.그것이 의식적인 이유였다는 것을 모릅니다.

언급URL : https://stackoverflow.com/questions/2404978/why-are-assertequals-parameters-in-the-order-expected-actual

반응형