def allow_fail(max_times_fail=1, silent=True):
    """Runs a test, if necessary repeatedly, allowing it to fail up to max_times_fail times.

    Usage:

    @allow_fail
    def test: ...
    # allows the test to be repeated once before considering the test failed

    @allow_fail(max_times_fail=2, silent=False)
    def test(): ...
    # allows the test to be repeated twice, printing a message on each failure

    This is useful if a test tests non-deterministic behavior, such as with stochastic
    algorithms. If the tests fails with probability p < 1, allowing it to fail n times
    causes the resulting test to fail with probability p^(n+1) < p.

    In particular it was written to test neural networks which are initialized randomly.

    :param max_times_fail: How often a test may fail before considering the test failed.
    :param silent: If False, prints a message before running the test and on each failure.
    :return: The decorated test method
    """

    def allow_fail_decorator(func):
        """
        :param func: The test allowed to be run repeatedly if it fails.
        :return: The decorated test function
        """
        def run_test_checked(self):
            """ Runs the test, repeating it up to max_times_fail times if it fails.
            :param self: The test suite, presumably an object of type unittest.TestCase
            """
            if not silent:
                print(
                    '\ntrying {}.{}() max. {} times'.format(
                        type(self).__name__, func.__name__, max_times_fail + 1
                    )
                )
            for i in range(max_times_fail):
                try:
                    func(self)
                    return
                except AssertionError:
                    if not silent:
                        print('failed {} times'.format(i+1))
            # run the test unguarded for a last time
            func(self)

        return run_test_checked

    return allow_fail_decorator