Typically, when an assertion fails, the xUnit frameworks aborts the testcase by throwing out an exception, or, with exception-less languages, issuing a return statement.
Depending on its framework, one knows which test failed thanks to the documentation message that goes with the assertion, thanks to the name of the asserted variable, or thanks to the location of the failure in the source code (file and line number).
However, if a testcase comprises several assertions, this prevents getting the outcome of the subsequent ones, which could be helpful in determining the root-cause of the red bar.
Hence, having no more than one assertion per test case can provide a better diagnostics as one get the result of all the assertions, not just the first one in the test case. example to come here
The drawback is that this duplicates the test case.
Sometimes, assertions are used as guard conditions: imagine a test invoking a function returning an object or a pointer to an object. Asserting that the object (or pointer) is not null, allows the test case to exit before attempting to access the object which will trigger a NullPointerException or a segmentation violation.
example to come here
That way, the test exits with an error message clearly indicating the origin of the failure.
As the way of Testivus is pointing out, don't bear any dogma, embrace unit testing karma.
It's more a matter of style, after all. Follow the rule that suits your need the most, grow your tests suite the TDD way, always keeping in mind the customer values working code, whatever the number of assertions per testcase.
Moreover, refactoring the unit tests from one assert per test to a single test case with multiple assertions is straightforward and could remove some duplication.
Moreover, Object-Oriented languages allow comparing instances of object, while testing the same thing with languages that have lower expressivity level can require several assertions.