/// <summary>
        /// Test an observable by creating a TestObserver and subscribing
        /// it to the <paramref name="source"/> observable.
        /// </summary>
        /// <typeparam name="T">The value type of the source observable.</typeparam>
        /// <param name="source">The source observable to test.</param>
        /// <returns>The new TestObserver instance.</returns>
        public static TestObserver <T> Test <T>(this IObservable <T> source)
        {
            RequireNonNull(source, nameof(source));
            var to = new TestObserver <T>();

            to.OnSubscribe(source.Subscribe(to));
            return(to);
        }
        /// <summary>
        /// Test the source by exhaustively consuming it, requiring it to support the
        /// <see cref="IAsyncFusedEnumerator{T}"/> interface, and returning
        /// a TestObserver with the results.
        /// </summary>
        /// <typeparam name="T">The element type of the sequence.</typeparam>
        /// <param name="source">The async enumerable sequence to test.</param>
        /// <returns>The task with the TestObserver instance</returns>
        public static async Task <TestObserver <T> > TestAsyncFused <T>(this IAsyncEnumerable <T> source)
        {
            var to = new TestObserver <T>();
            var en = source.GetAsyncEnumerator();
            var f  = en as IAsyncFusedEnumerator <T>;

            if (f == null)
            {
                throw new ArgumentException("The IAsyncEnumerator returned by source is not fuseable");
            }
            try
            {
                for (; ;)
                {
                    var v = f.TryPoll(out var state);

                    if (state == AsyncFusedState.Ready)
                    {
                        to.OnNext(v);
                    }
                    else if (state == AsyncFusedState.Terminated)
                    {
                        to.OnCompleted();
                        break;
                    }
                    else if (!await en.MoveNextAsync())
                    {
                        to.OnCompleted();
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                to.OnError(ex);
            }
            finally
            {
                await en.DisposeAsync();
            }
            return(to);
        }
        /// <summary>
        /// Test the source by exhaustively consuming it and returning
        /// a TestObserver with the results.
        /// </summary>
        /// <typeparam name="T">The element type of the sequence.</typeparam>
        /// <param name="source">The async enumerable sequence to test.</param>
        /// <returns>The task with the TestObserver instance</returns>
        public static async Task <TestObserver <T> > TestAsync <T>(this IAsyncEnumerable <T> source)
        {
            var to = new TestObserver <T>();
            var en = source.GetAsyncEnumerator();

            try
            {
                while (await en.MoveNextAsync())
                {
                    to.OnNext(en.Current);
                }
                to.OnCompleted();
            }
            catch (Exception ex)
            {
                to.OnError(ex);
            }
            finally
            {
                await en.DisposeAsync();
            }
            return(to);
        }