ExampleTests.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #nullable enable
  2. using System.Diagnostics.CodeAnalysis;
  3. using Terminal.Gui.Examples;
  4. using Xunit.Abstractions;
  5. namespace UnitTests.Parallelizable.Examples;
  6. /// <summary>
  7. /// Tests for the example discovery and execution infrastructure.
  8. /// </summary>
  9. public class ExampleTests
  10. {
  11. private readonly ITestOutputHelper _output;
  12. public ExampleTests (ITestOutputHelper output)
  13. {
  14. _output = output;
  15. }
  16. /// <summary>
  17. /// Discovers all examples by looking for assemblies with ExampleMetadata attributes.
  18. /// </summary>
  19. /// <returns>Test data for all discovered examples.</returns>
  20. [RequiresUnreferencedCode ("Calls ExampleDiscovery.DiscoverFromDirectory")]
  21. [RequiresDynamicCode ("Calls ExampleDiscovery.DiscoverFromDirectory")]
  22. public static IEnumerable<object []> AllExamples ()
  23. {
  24. string examplesDir = Path.GetFullPath (Path.Combine (AppContext.BaseDirectory, "..", "..", "..", "..", "..", "Examples"));
  25. if (!Directory.Exists (examplesDir))
  26. {
  27. return [];
  28. }
  29. List<ExampleInfo> examples = ExampleDiscovery.DiscoverFromDirectory (examplesDir).ToList ();
  30. if (examples.Count == 0)
  31. {
  32. return [];
  33. }
  34. return examples.Select (e => new object [] { e });
  35. }
  36. [Theory]
  37. [MemberData (nameof (AllExamples))]
  38. public void Example_Has_Metadata (ExampleInfo example)
  39. {
  40. Assert.NotNull (example);
  41. Assert.False (string.IsNullOrWhiteSpace (example.Name), "Example name should not be empty");
  42. Assert.False (string.IsNullOrWhiteSpace (example.Description), "Example description should not be empty");
  43. Assert.True (File.Exists (example.AssemblyPath), $"Example assembly should exist: {example.AssemblyPath}");
  44. _output.WriteLine ($"Example: {example.Name}");
  45. _output.WriteLine ($" Description: {example.Description}");
  46. _output.WriteLine ($" Categories: {string.Join (", ", example.Categories)}");
  47. _output.WriteLine ($" Assembly: {example.AssemblyPath}");
  48. }
  49. [Theory]
  50. [MemberData (nameof (AllExamples))]
  51. public void All_Examples_Quit_And_Init_Shutdown_Properly_OutOfProcess (ExampleInfo example)
  52. {
  53. _output.WriteLine ($"Running example '{example.Name}' out-of-process");
  54. ExampleContext context = new ()
  55. {
  56. DriverName = "FakeDriver",
  57. KeysToInject = new () { "Esc" },
  58. TimeoutMs = 5000,
  59. CollectMetrics = false,
  60. Mode = ExecutionMode.OutOfProcess
  61. };
  62. ExampleResult result = ExampleRunner.Run (example, context);
  63. if (!result.Success)
  64. {
  65. _output.WriteLine ($"Example failed: {result.ErrorMessage}");
  66. if (!string.IsNullOrEmpty (result.StandardOutput))
  67. {
  68. _output.WriteLine ($"Standard Output:\n{result.StandardOutput}");
  69. }
  70. if (!string.IsNullOrEmpty (result.StandardError))
  71. {
  72. _output.WriteLine ($"Standard Error:\n{result.StandardError}");
  73. }
  74. }
  75. Assert.True (result.Success, $"Example '{example.Name}' should complete successfully");
  76. Assert.False (result.TimedOut, $"Example '{example.Name}' should not timeout");
  77. Assert.Equal (0, result.ExitCode);
  78. }
  79. [Theory]
  80. [MemberData (nameof (AllExamples))]
  81. public void All_Examples_Quit_And_Init_Shutdown_Properly_InProcess (ExampleInfo example)
  82. {
  83. _output.WriteLine ($"Running example '{example.Name}' in-process");
  84. // Force a complete reset to ensure clean state
  85. Application.ResetState (true);
  86. ExampleContext context = new ()
  87. {
  88. DriverName = "FakeDriver",
  89. KeysToInject = new () { "Esc" },
  90. TimeoutMs = 5000,
  91. CollectMetrics = false,
  92. Mode = ExecutionMode.InProcess
  93. };
  94. ExampleResult result = ExampleRunner.Run (example, context);
  95. if (!result.Success)
  96. {
  97. _output.WriteLine ($"Example failed: {result.ErrorMessage}");
  98. }
  99. // Reset state after in-process execution
  100. Application.ResetState (true);
  101. Assert.True (result.Success, $"Example '{example.Name}' should complete successfully");
  102. Assert.False (result.TimedOut, $"Example '{example.Name}' should not timeout");
  103. }
  104. [Fact]
  105. public void ExampleContext_Serialization_Works ()
  106. {
  107. ExampleContext context = new ()
  108. {
  109. DriverName = "FakeDriver",
  110. KeysToInject = new () { "Esc", "Enter" },
  111. TimeoutMs = 5000,
  112. MaxIterations = 100,
  113. CollectMetrics = true,
  114. Mode = ExecutionMode.InProcess
  115. };
  116. string json = context.ToJson ();
  117. Assert.False (string.IsNullOrWhiteSpace (json));
  118. ExampleContext? deserialized = ExampleContext.FromJson (json);
  119. Assert.NotNull (deserialized);
  120. Assert.Equal (context.DriverName, deserialized.DriverName);
  121. Assert.Equal (context.TimeoutMs, deserialized.TimeoutMs);
  122. Assert.Equal (context.MaxIterations, deserialized.MaxIterations);
  123. Assert.Equal (context.CollectMetrics, deserialized.CollectMetrics);
  124. Assert.Equal (context.Mode, deserialized.Mode);
  125. Assert.Equal (context.KeysToInject.Count, deserialized.KeysToInject.Count);
  126. }
  127. }