How to use TestRunAttachmentsProcessingManager class of Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing package

Best Vstest code snippet using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing.TestRunAttachmentsProcessingManager

TestRunAttachmentsProcessingManager.cs

Source:TestRunAttachmentsProcessingManager.cs Github

copy

Full Screen

...18{19 /// <summary>20 /// Orchestrates test run attachments processing operations.21 /// </summary>22 public class TestRunAttachmentsProcessingManager : ITestRunAttachmentsProcessingManager23 {24 private static string AttachmentsProcessingCompleted = "Completed";25 private static string AttachmentsProcessingCanceled = "Canceled";26 private static string AttachmentsProcessingFailed = "Failed";27 private readonly ITestPlatformEventSource testPlatformEventSource;28 private readonly IDataCollectorAttachmentProcessor[] dataCollectorAttachmentsProcessors;29 /// <summary>30 /// Initializes a new instance of the <see cref="TestRunAttachmentsProcessingManager"/> class.31 /// </summary>32 public TestRunAttachmentsProcessingManager(ITestPlatformEventSource testPlatformEventSource, params IDataCollectorAttachmentProcessor[] dataCollectorAttachmentsProcessors)33 {34 this.testPlatformEventSource = testPlatformEventSource ?? throw new ArgumentNullException(nameof(testPlatformEventSource));35 this.dataCollectorAttachmentsProcessors = dataCollectorAttachmentsProcessors ?? throw new ArgumentNullException(nameof(dataCollectorAttachmentsProcessors));36 }37 /// <inheritdoc/>38 public async Task ProcessTestRunAttachmentsAsync(IRequestData requestData, IEnumerable<AttachmentSet> attachments, ITestRunAttachmentsProcessingEventsHandler eventHandler, CancellationToken cancellationToken)39 {40 await InternalProcessTestRunAttachmentsAsync(requestData, new Collection<AttachmentSet>(attachments.ToList()), eventHandler, cancellationToken).ConfigureAwait(false);41 }42 /// <inheritdoc/>43 public Task<Collection<AttachmentSet>> ProcessTestRunAttachmentsAsync(IRequestData requestData, IEnumerable<AttachmentSet> attachments, CancellationToken cancellationToken)44 {45 return InternalProcessTestRunAttachmentsAsync(requestData, new Collection<AttachmentSet>(attachments.ToList()), null, cancellationToken);46 }47 private async Task<Collection<AttachmentSet>> InternalProcessTestRunAttachmentsAsync(IRequestData requestData, Collection<AttachmentSet> attachments, ITestRunAttachmentsProcessingEventsHandler eventHandler, CancellationToken cancellationToken)48 {49 Stopwatch stopwatch = Stopwatch.StartNew();50 try51 {52 testPlatformEventSource.TestRunAttachmentsProcessingStart(attachments?.Count ?? 0);53 requestData.MetricsCollection.Add(TelemetryDataConstants.NumberOfAttachmentsSentForProcessing, attachments?.Count ?? 0);54 55 cancellationToken.ThrowIfCancellationRequested(); 56 var taskCompletionSource = new TaskCompletionSource<Collection<AttachmentSet>>();57 using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))58 {59 Task<Collection<AttachmentSet>> task = Task.Run(async () => await ProcessAttachmentsAsync(new Collection<AttachmentSet>(attachments.ToList()), eventHandler, cancellationToken));60 var completedTask = await Task.WhenAny(task, taskCompletionSource.Task).ConfigureAwait(false);61 if (completedTask == task)62 {63 return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(false, null), await task, stopwatch, eventHandler);64 }65 else66 {67 eventHandler?.HandleLogMessage(TestMessageLevel.Informational, "Attachments processing was cancelled.");68 return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(true, null), attachments, stopwatch, eventHandler);69 }70 }71 }72 catch (OperationCanceledException)73 {74 if (EqtTrace.IsWarningEnabled)75 {76 EqtTrace.Warning("TestRunAttachmentsProcessingManager: operation was cancelled.");77 }78 return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(true, null), attachments, stopwatch, eventHandler);79 }80 catch (Exception e)81 {82 EqtTrace.Error("TestRunAttachmentsProcessingManager: Exception in ProcessTestRunAttachmentsAsync: " + e);83 eventHandler?.HandleLogMessage(TestMessageLevel.Error, e.Message);84 return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(false, e), attachments, stopwatch, eventHandler);85 }86 }87 private async Task<Collection<AttachmentSet>> ProcessAttachmentsAsync(Collection<AttachmentSet> attachments, ITestRunAttachmentsProcessingEventsHandler eventsHandler, CancellationToken cancellationToken)88 {89 if (attachments == null || !attachments.Any()) return attachments;90 var logger = CreateMessageLogger(eventsHandler);91 for (int i = 0; i < dataCollectorAttachmentsProcessors.Length; i++)92 {93 var dataCollectorAttachmentsProcessor = dataCollectorAttachmentsProcessors[i];94 int attachmentsHandlerIndex = i + 1;95 ICollection<Uri> attachmentProcessorUris = dataCollectorAttachmentsProcessor.GetExtensionUris()?.ToList();96 if (attachmentProcessorUris != null && attachmentProcessorUris.Any())...

Full Screen

Full Screen

Fixture.cs

Source:Fixture.cs Github

copy

Full Screen

...30 public FakeTestPlatformEventSource? TestPlatformEventSource { get; private set; }31 public FakeAssemblyMetadataProvider? AssemblyMetadataProvider { get; private set; }32 public InferHelper? InferHelper { get; private set; }33 public FakeDataCollectorAttachmentsProcessorsFactory? DataCollectorAttachmentsProcessorsFactory { get; private set; }34 public TestRunAttachmentsProcessingManager? TestRunAttachmentsProcessingManager { get; private set; }35 public TestRequestManager? TestRequestManager { get; private set; }36 public ProtocolConfig ProtocolConfig { get; internal set; }37 public List<TestResult> ExecutedTests => TestRunEventsRegistrar.RunChangedEvents.SelectMany(er => er.Data.NewTestResults!).ToList();38 public List<TestCase> DiscoveredTests => TestDiscoveryEventsRegistrar.DiscoveredTestsEvents.SelectMany(er => er.Data.DiscoveredTestCases!).ToList();39 public List<string> LoggedWarnings => TestRunEventsRegistrar.LoggedWarnings.Concat(TestDiscoveryEventsRegistrar.LoggedWarnings).ToList();40 public FakeTestSessionEventsHandler TestSessionEventsHandler { get; }41 public Fixture(FixtureOptions? fixtureOptions = null)42 {43 // This type is compiled only in DEBUG, and won't exist otherwise.44#if DEBUG45 // We need to use static class to find the communication endpoint, this clears all the registrations of previous tests.46 TestServiceLocator.Clear();47#else48 // This fools compiler into not being able to tell that the the rest of the code is unreachable.49 var a = true;50 if (a)51 {52 throw new InvalidOperationException("Tests cannot run in Release mode, because TestServiceLocator is compiled only for Debug, and so the tests will fail to setup channel and will hang.");53 }54#endif55#pragma warning disable CS0618 // Type or member is obsolete (to prevent use outside of test context)56 FeatureFlag.Reset();57 fixtureOptions?.FeatureFlags?.ToList().ForEach(flag => ((FeatureFlag)FeatureFlag.Instance).SetFlag(flag.Key, flag.Value));58#pragma warning restore CS0618 // Type or member is obsolete59 // This makes the run a bit slower, but at least we get info in the output window. We probably should add a mode where we don't60 // use a file to write the output. Just trace listener. That would also be useful for UWP I think.61 LogName = Path.GetTempPath() + $"/log_{Guid.NewGuid()}.txt";62 //EqtTrace.InitializeVerboseTrace(LogName);63 CurrentProcess = new FakeProcess(ErrorAggregator, @"X:\fake\vstest.console.exe");64 ProcessHelper = new FakeProcessHelper(ErrorAggregator, CurrentProcess);65 FileHelper = new FakeFileHelper(ErrorAggregator);66 TestRuntimeProviderManager = new FakeTestRuntimeProviderManager(ErrorAggregator);67 TestRunEventsRegistrar = new FakeTestRunEventsRegistrar(ErrorAggregator);68 Environment = new FakeEnvironment();69 TestDiscoveryEventsRegistrar = new FakeTestDiscoveryEventsRegistrar(ErrorAggregator);70 TestSessionEventsHandler = new FakeTestSessionEventsHandler(ErrorAggregator);71 ProtocolConfig = new ProtocolConfig();72 }73 public void Dispose()74 {75 foreach (var disposable in _disposables)76 {77 try { disposable.Dispose(); } catch (ObjectDisposedException) { }78 }79 }80 internal void AddTestHostFixtures(params FakeTestHostFixture[] testhosts)81 {82 _disposables.AddRange(testhosts);83 var providers = testhosts.Select(t => t.FakeTestRuntimeProvider).ToArray();84 TestRuntimeProviderManager.AddTestRuntimeProviders(providers);85 }86 internal TestRequestManagerTestHelper BuildTestRequestManager(87 int? timeout = DebugOptions.DefaultTimeout,88 int? debugTimeout = DebugOptions.DefaultDebugTimeout,89 bool? breakOnAbort = DebugOptions.DefaultBreakOnAbort)90 {91 if (!TestRuntimeProviderManager.TestRuntimeProviders.Any())92 throw new InvalidOperationException("There are runtime providers registered for FakeTestRuntimeProviderManager.");93 TestEngine = new TestEngine(TestRuntimeProviderManager, ProcessHelper, Environment);94 TestPlatform = new TestPlatform(TestEngine, FileHelper, TestRuntimeProviderManager);95 TestRunResultAggregator = new TestRunResultAggregator();96 TestPlatformEventSource = new FakeTestPlatformEventSource(ErrorAggregator);97 AssemblyMetadataProvider = new FakeAssemblyMetadataProvider(FileHelper, ErrorAggregator);98 InferHelper = new InferHelper(AssemblyMetadataProvider);99 // This is most likely not the correctl place where to cut this off, plugin cache is probably the better place,100 // but it is not injected, and I don't want to investigate this now.101 DataCollectorAttachmentsProcessorsFactory = new FakeDataCollectorAttachmentsProcessorsFactory(ErrorAggregator);102 TestRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager(TestPlatformEventSource, DataCollectorAttachmentsProcessorsFactory);103 Task<IMetricsPublisher> fakeMetricsPublisherTask = Task.FromResult<IMetricsPublisher>(new FakeMetricsPublisher(ErrorAggregator));104 var commandLineOptions = new CommandLineOptions105 {106 // We are acting like we are running under IDE. This is done because some settings are trying to grab the107 // value from the pre-parsed settings in command line options. And some are looking at the actual run settings.108 // Ultimately we should have a single point of truth for both scenarios, but now it is easier to just provide109 // runsettings to the request.110 IsDesignMode = true,111 };112 TestRequestManager testRequestManager = new(113 commandLineOptions,114 TestPlatform,115 TestRunResultAggregator,116 TestPlatformEventSource,117 InferHelper,118 fakeMetricsPublisherTask,119 ProcessHelper,120 TestRunAttachmentsProcessingManager,121 Environment);122 TestRequestManager = testRequestManager;123 return new TestRequestManagerTestHelper(ErrorAggregator, testRequestManager, new DebugOptions124 {125 Timeout = timeout ?? DebugOptions.DefaultTimeout,126 DebugTimeout = debugTimeout ?? DebugOptions.DefaultDebugTimeout,127 BreakOnAbort = breakOnAbort ?? DebugOptions.DefaultBreakOnAbort,128 });129 }130 internal void AssertNoErrors()131 {132 ErrorAggregator.Errors.Should().BeEmpty();133 }134}...

Full Screen

Full Screen

TestRunAttachmentsProcessingManager

Using AI Code Generation

copy

Full Screen

1using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;2using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;3using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;4using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;5using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;6using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;7using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;8using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;9using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;10using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;11using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;

Full Screen

Full Screen

TestRunAttachmentsProcessingManager

Using AI Code Generation

copy

Full Screen

1using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;2{3 {4 static void Main(string[] args)5 {6 TestRunAttachmentsProcessingManager testRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager();7 testRunAttachmentsProcessingManager.Initialize();8 testRunAttachmentsProcessingManager.ProcessTestRunAttachments();9 }10 }11}12using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;13{14 {15 static void Main(string[] args)16 {17 TestRunAttachmentsProcessingManager testRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager();18 testRunAttachmentsProcessingManager.Initialize();19 testRunAttachmentsProcessingManager.ProcessTestRunAttachments();20 }21 }22}23using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;24{25 {26 static void Main(string[] args)27 {28 TestRunAttachmentsProcessingManager testRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager();29 testRunAttachmentsProcessingManager.Initialize();30 testRunAttachmentsProcessingManager.ProcessTestRunAttachments();31 }32 }33}34using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;35{36 {37 static void Main(string[] args)38 {39 TestRunAttachmentsProcessingManager testRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager();40 testRunAttachmentsProcessingManager.Initialize();41 testRunAttachmentsProcessingManager.ProcessTestRunAttachments();42 }43 }44}45using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;46{47 {48 static void Main(string[] args)49 {50 TestRunAttachmentsProcessingManager testRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager();

Full Screen

Full Screen

TestRunAttachmentsProcessingManager

Using AI Code Generation

copy

Full Screen

1using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;2using Microsoft.VisualStudio.TestPlatform.ObjectModel;3using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;4using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol;5using System.Collections.Generic;6using System.IO;7{8 {9 public static void Main(string[] args)10 {11 var testRunAttachmentsProcessingManager = new Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing.TestRunAttachmentsProcessingManager();12 testRunAttachmentsProcessingManager.Initialize(Path.GetTempPath());13 var testRunAttachments = testRunAttachmentsProcessingManager.GetTestRunAttachments();14 testRunAttachmentsProcessingManager.ProcessTestRunAttachments(testRunAttachments);15 testRunAttachmentsProcessingManager.Initialize(Path.GetTempPath());16 testRunAttachments = testRunAttachmentsProcessingManager.GetTestRunAttachments();17 testRunAttachmentsProcessingManager.ProcessTestRunAttachments(testRunAttachments);18 }19 }20}21using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;22using Microsoft.VisualStudio.TestPlatform.ObjectModel;23using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;24using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol;25using System.Collections.Generic;26using System.IO;27{28 {29 public static void Main(string[] args)30 {31 var testRunAttachmentsProcessingManager = new Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing.TestRunAttachmentsProcessingManager();32 testRunAttachmentsProcessingManager.Initialize(Path.GetTempPath());33 var testRunAttachments = testRunAttachmentsProcessingManager.GetTestRunAttachments();

Full Screen

Full Screen

TestRunAttachmentsProcessingManager

Using AI Code Generation

copy

Full Screen

1using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;2using Microsoft.VisualStudio.TestPlatform.ObjectModel;3using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;4using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol;5using System.Collections.Generic;6using System.IO;7{8 {9 public static void Main(string[] args)10 {11 var testRunAttachmentsProcessingManager = new Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing.TestRunAttachmentsProcessingManager();12 testRunAttachmentsProcessingManager.Initialize(Path.GetTempPath());13 var testRunAttachments = testRunAttachmentsProcessingManager.GetTestRunAttachments();14 testRunAttachmentsProcessingManager.ProcessTestRunAttachments(testRunAttachments);15 testRunAttachmentsProcessingManager.Initialize(Path.GetTempPath());16 testRunAttachments = testRunAttachmentsProcessingManager.GetTestRunAttachments();17 testRunAttachmentsProcessingManager.ProcessTestRunAttachments(testRunAttachments);18 }19 }20}21using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;22using Microsoft.VisualStudio.TestPlatform.ObjectModel;23using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;24using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol;25using System.Collections.Generic;26using System.IO;27{28 {29 public static void Main(string[] args)30 {31 var testRunAttachmentsProcessingManager = new Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing.TestRunAttachmentsProcessingManager();32 testRunAttachmentsProcessingManager.Initialize(Path.GetTempPath());33 var testRunAttachments = testRunAttachmentsProcessingManager.GetTestRunAttachments();

Full Screen

Full Screen

TestRunAttachmentsProcessingManager

Using AI Code Generation

copy

Full Screen

1using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;2using Microsoft.VisualStudio.TestPlatform.ObjectModel;3using System.Collections.Generic;4using System.IO;5{6 {7 static void Main(string[] args)8 {9 var attachments = new List<AttachmentSet>();10 attachmentSet.Attachments.Add(new Attachment("C:\\temp\\coverage.info", "coverage.info"));11 attachments.Add(attachmentSet);12 var manager = new TestRunAttachmentsProcessingManager();13 manager.Initialize(new TestLoggerEvents(null));14 manager.ProcessTestRunAttachments(attachments, "C:\\temp\\attachments");15 manager.Dispose();16 var files = Directory.GetFiles("C:\\temp\\attachments");17 foreach (var file in files)18 {19 File.Delete(file);20 }21 }22 }23}24using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;25using Microsoft.VisualStudio.TestPlatform.ObjectModel;26using System.Collections.Generic;27using System.IO;28{29 {30 static void Main(string[] args)31 {32 var attachments = new List<AttachmentSet>();33 attachmentSet.Attachments.Add(new Attachment("C:\\temp\\coverage.info", "coverage.info"));34 attachments.Add(attachmentSet);

Full Screen

Full Screen

TestRunAttachmentsProcessingManager

Using AI Code Generation

copy

Full Screen

1using System;2using System.Collections.Generic;3using System.IO;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;8{9 {10 static void Main(string[] args)11 {12 string runAttachments = @"C:\Users\{username}\AppData\Local\Temp\VisualStudioTestExplorerExtensions\{GUID}\RunAttachments";13 string codeCoverageFile = @"C:\Users\{username}\AppData\Local\Temp\VisualStudioTestExplorerExtensions\{GUID}\CodeCoverageFile";14 TestRunAttachmentsProcessingManager testRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager();15 testRunAttachmentsProcessingManager.ProcessTestRunAttachments(runAttachments, codeCoverageFile);16 Console.WriteLine("Done");17 Console.ReadLine();18 }19 }20}21 manager.Initialize(new TestLoggerEvents(null));.TestRunAttachmentsProcessing package22using System;23using System.Collections.Generic;24using System.IO;25using System.Linq;26using System.Text;27using System.Threading.Tasks;28using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;29{30 {31 static void Main(string[] args)32 {33 string runAttachments = @"C:\Users\{username}\AppData\Local\Temp\VisualStudioTestExplorerExtensions\{GUID}\RunAttachments";34 string codeCoverageFile = @"C:\Users\{username}\AppData\Local\Temp\VisualStudioTestExplorerExtensions\{GUID}\CodeCoverageFile";35 TestRunAttachmentsProcessingManager testRunAttachmentsProcessingManager = new TestRunAttachmentsProcessingManager();36 testRunAttachmentsProcessingManager.ProcessTestRunAttachments(runAttachments, codeCoverageFile);37 Console.WriteLine("Done");38 Console.ReadLine();39 }40 }41}42using System;43using System.Collections.Generic;44using System.IO;45using System.Linq;46using System.Text;47using System.Threading.Tasks;48using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing;49 manager.ProcessTestRunAttachments(attachments, "C:\\temp\\attachments");50 manager.Dispose();51 var files = Directory.GetFiles("C:\\temp\\attachments");52 foreach (var file in files)53 {54 File.Delete(file);55 }56 }57 }58}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Vstest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful