Programing

Assert.Fail ()은 나쁜 습관으로 간주됩니까?

lottogame 2020. 11. 12. 07:40
반응형

Assert.Fail ()은 나쁜 습관으로 간주됩니까?


나는 Assert를 사용하고 TDD를 할 때 많은 실패를한다. 저는 보통 한 번에 하나의 테스트를 진행하고 있지만 나중에 구현하고 싶은 것에 대한 아이디어를 얻으면 테스트 메서드의 이름이 일종의 할 일 목록으로 구현하려는 것을 나타내는 빈 테스트를 빠르게 작성합니다. 잊지 않도록 Assert.Fail ()을 본문에 넣었습니다.

xUnit.Net을 사용해 보았을 때 Assert.Fail을 구현하지 않은 것으로 나타났습니다. 물론 항상 Assert.IsTrue (false)를 사용할 수 있지만 이것은 내 의도를 전달하지도 않습니다. Assert.Fail이 의도적으로 구현되지 않은 인상을 받았습니다. 이것은 나쁜 습관으로 간주됩니까? 그렇다면 왜?


@Martin Meredith 그건 정확히 내가하는 일이 아닙니다. 먼저 테스트를 작성한 다음 코드를 구현하여 작동합니다. 일반적으로 한 번에 여러 테스트를 생각합니다. 또는 다른 작업을 할 때 작성할 테스트에 대해 생각합니다. 그때 기억하기 위해 빈 실패한 테스트를 작성했습니다. 테스트를 작성할 때 쯤이면 테스트부터 깔끔하게 작업합니다.

@Jimmeh 좋은 생각 같네요. 무시 된 테스트는 실패하지 않지만 여전히 별도의 목록에 표시됩니다. 그것을 시도해야합니다.

@Matt Howells 훌륭한 아이디어. 이 경우 NotImplementedException은 assert.Fail ()보다 의도를 더 잘 전달합니다.

@Mitch Wheat 그게 제가 찾던 것입니다. 내가 남용하는 다른 방법으로 남용되는 것을 막기 위해 빠진 것 같습니다.


이 시나리오에서는 Assert.Fail을 호출하는 대신 다음을 수행합니다 (C # / NUnit에서).

[Test]
public void MyClassDoesSomething()
{
    throw new NotImplementedException();
}

Assert.Fail보다 더 명시 적입니다.

Assert.Fail ()보다 더 명시적인 단언을 사용하는 것이 바람직하다는 일반적인 동의가있는 것 같습니다. 대부분의 프레임 워크는 더 나은 대안을 제공하지 않기 때문에이를 포함해야합니다. 예를 들어 NUnit (및 기타)은 일부 코드에서 특정 예외 클래스를 throw하는지 테스트하기 위해 ExpectedExceptionAttribute를 제공합니다. 그러나 예외 속성이 특정 값으로 설정되어 있는지 테스트하기 위해 사용할 수 없습니다. 대신 Assert에 의존해야합니다.

[Test]
public void ThrowsExceptionCorrectly()
{
    const string BAD_INPUT = "bad input";
    try
    {
        new MyClass().DoSomething(BAD_INPUT);
        Assert.Fail("No exception was thrown");
    }
    catch (MyCustomException ex)
    {
         Assert.AreEqual(BAD_INPUT, ex.InputString); 
    }
}

xUnit.Net 메서드 Assert.Throws를 사용하면 Assert.Fail 메서드 없이도이를 훨씬 깔끔하게 만들 수 있습니다. Assert.Fail () 메서드를 포함하지 않음으로써 xUnit.Net은 개발자가보다 명시적인 대안을 찾아 사용하고 필요한 경우 새 어설 션 생성을 지원하도록 권장합니다.


의도적으로 제외되었습니다. 이것은 Assert.Fail ()이없는 이유에 대한 Brad Wilson의 답변입니다.

사실 우리는 이것을 간과하지 않았습니다. Assert.Fail은 아마도 주장이 누락되었음을 의미하는 목발입니다. 때로는 테스트가 구조화 된 방식이고 때로는 Assert가 다른 어설 션을 사용할 수 있기 때문입니다.


저는 항상 Assert.Fail ()을 사용하여 테스트가 단순한 값 비교 이상의 논리를 통해 실패해야한다는 것을 감지 한 경우를 처리했습니다. 예로서:

try 
{
  // Some code that should throw ExceptionX
  Assert.Fail("ExceptionX should be thrown")
} 
catch ( ExceptionX ex ) 
{
  // test passed
}

따라서 프레임 워크에 Assert.Fail ()이 없다는 것은 나에게 실수처럼 보입니다. Fail () 메서드를 포함하도록 Assert 클래스를 패치 한 다음 추가 이유와 함께 프레임 워크 개발자에게 패치를 제출하는 것이 좋습니다.

작업 공간에서 의도적으로 실패한 테스트를 만드는 연습에 관해서는 커밋하기 전에 구현하도록 상기시키는 것이 나에게 좋은 연습처럼 보입니다.


단위 테스트에 MbUnit을 사용합니다. 테스트 스위트에서 주황색 (녹색 또는 빨간색이 아닌)으로 표시되는 테스트 무시 옵션이 있습니다. 아마도 xUnit은 비슷한 것을 가지고 있고, 당신이 어떤 어설 션도 메소드에 넣을 필요가 없다는 것을 의미 할 것입니다. 왜냐하면 그것이 성가 시게 다른 색상으로 나타나서 놓치기 어렵 기 때문입니다.

편집하다:

MbUnit에서는 다음과 같은 방식입니다.

[Test]
[Ignore]
public void YourTest()
{ } 

이것은 설계 상 예외를 던지고 싶은 코드에 대한 테스트를 작성할 때 사용하는 패턴입니다.

[TestMethod]
public void TestForException()
{
    Exception _Exception = null;

    try
    {
        //Code that I expect to throw the exception.
        MyClass _MyClass = null;
        _MyClass.SomeMethod();
        //Code that I expect to throw the exception.
    }
    catch(Exception _ThrownException)
    {   
        _Exception = _ThrownException
    }
    finally
    {
        Assert.IsNotNull(_Exception);
        //Replace NullReferenceException with expected exception.
        Assert.IsInstanceOfType(_Exception, typeof(NullReferenceException));
    }
}

IMHO this is a better way of testing for exceptions over using Assert.Fail(). The reason for this is that not only do I test for an exception being thrown at all but I also test for the exception type. I realise that this is similar to the answer from Matt Howells but IMHO using the finally block is more robust.

Obviously it would still be possible to include other Assert methods to test the exceptions input string etc. I would be grateful for your comments and views on my pattern.


Personally I have no problem with using a test suite as a todo list like this as long as you eventually get around to writing the test before you implement the code to pass.

Having said that, I used to use this approach myself, although now I'm finding that doing so leads me down a path of writing too many tests upfront, which in a weird way is like the reverse problem of not writing tests at all: you end up making decisions about design a little too early IMHO.

Incidentally in MSTest, the standard Test template uses Assert.Inconclusive at the end of its samples.

AFAIK the xUnit.NET framework is intended to be extremely lightweight and yes they did cut Fail deliberately, to encourage the developer to use an explicit failure condition.


Wild guess: withholding Assert.Fail is intended to stop you thinking that a good way to write test code is as a huge heap of spaghetti leading to an Assert.Fail in the bad cases. [Edit to add: other people's answers broadly confirm this, but with quotations]

Since that's not what you're doing, it's possible that xUnit.Net is being over-protective.

Or maybe they just think it's so rare and so unorthogonal as to be unnecessary.

I prefer to implement a function called ThisCodeHasNotBeenWrittenYet (actually something shorter, for ease of typing). Can't communicate intention more clearly than that, and you have a precise search term.

Whether that fails, or is not implemented (to provoke a linker error), or is a macro that doesn't compile, can be changed to suit your current preference. For instance when you want to run something that is finished, you want a fail. When you're sitting down to get rid of them all, you may want a compile error.


With the good code I usually do:

void goodCode() {
     // TODO void goodCode()
     throw new NotSupportedOperationException("void goodCode()");
}

With the test code I usually do:

@Test
void testSomething() {
     // TODO void test Something
     Assert.assert("Some descriptive text about what to test")
}

If using JUnit, and don't want to get the failure, but the error, then I usually do:

@Test
void testSomething() {
     // TODO void test Something
     throw new NotSupportedOperationException("Some descriptive text about what to test")
}

Beware Assert.Fail and its corrupting influence to make developers write silly or broken tests. For example:

[TestMethod]
public void TestWork()
{
    try {
        Work();
    }
    catch {
        Assert.Fail();
    }
}

This is silly, because the try-catch is redundant. A test fails if it throws an exception.

Also

[TestMethod]
public void TestDivide()
{
    try {
        Divide(5,0);
        Assert.Fail();
    } catch { }
}

This is broken, the test will always pass whatever the outcome of the Divide function. Again, a test fails if and only if it throws an exception.


If you're writing a test that just fails, and then writing the code for it, then writing the test. This isn't Test Driven Development.

Technically, Assert.fail() shouldn't be needed if you're using test driven development correctly.

Have you thought of using a Todo List, or applying a GTD methodology to your work?


MS Test has Assert.Fail() but it also has Assert.Inconclusive(). I think that the most appropriate use for Assert.Fail() is if you have some in-line logic that would be awkward to put in an assertion, although I can't even think of any good examples. For the most part, if the test framework supports something other than Assert.Fail() then use that.


I think you should ask yourselves what (upfront) testing should do.

First, you write a (set of) test without implmentation. Maybe, also the rainy day scenarios.

All those tests must fail, to be correct tests: So you want to achieve two things: 1) Verify that your implementation is correct; 2) Verify that your unit tests are correct.

Now, if you do upfront TDD, you want to execute all your tests, also, the NYI parts. The result of your total test run passes if: 1) All implemented stuff succeeds 2) All NYI stuff fails

After all, it would be a unit test ommision if your unit tests succeeds whilst there is no implementation, isnt it?

You want to end up with something of a mail of your continous integration test that checks all implemented and not implemented code, and is sent if any implemented code fails, or any not implemented code succeeds. Both are undesired results.

Just write an [ignore] tests wont do the job. Neither, an asserts that stops an the first assert failure, not running other tests lines in the test.

Now, how to acheive this then? I think it requires some more advanced organisation of your testing. And it requires some other mechanism then asserts to achieve these goals.

I think you have to split up your tests and create some tests that completly run but must fail, and vice versa.

Ideas are to split your tests over multiple assemblies, use grouping of tests (ordered tests in mstest may do the job).

Still, a CI build that mails if not all tests in the NYI department fail is not easy and straight-forward.


Why would you use Assert.Fail for saying that an exception should be thrown? That is unnecessary. Why not just use the ExpectedException attribute?

참고URL : https://stackoverflow.com/questions/120648/is-assert-fail-considered-bad-practice

반응형