Testing and Debugging

The Kubernetes Client library for C# utilizes XUnit as its unit testing framework. The tests are designed to verify the library’s functionality and ensure its correctness.

Running Tests

To execute the tests, navigate to the csharp/tests directory and run the following commands:

dotnet restore
          dotnet test
          

Debugging

For debugging, you can leverage the Visual Studio debugger. Set breakpoints in the code you want to inspect and initiate debugging. Alternatively, you can use the dotnet test command with the --debug flag to start the debugger.

Code Coverage

The project leverages code coverage analysis to assess the effectiveness of the test suite. The CodeCoverage.runsettings file defines exclusion rules for attributes such as ObsoleteAttribute, GeneratedCodeAttribute, DebuggerHiddenAttribute, and ExcludeFromCodeCoverageAttribute, ensuring that these are not factored into the coverage calculations.

Examples

Kubectl Tests

The tests/Kubectl.Tests/KubectlTests.cs file demonstrates testing for functionality related to the kubectl command-line tool.

using System.Diagnostics;
          
          namespace k8s.kubectl.Tests;
          

Model Extension Tests

The tests/KubernetesClient.Tests/ModelExtensionTests.cs file contains tests for various model extensions, including the V1Status model.

[Fact]
          public void TestV1Status()
          {
              var s = new V1Status() { Status = "Success" };
              Assert.Equal("Success", s.ToString());
          
              s = new V1Status() { Status = "Failure" };
              Assert.Equal("Failure", s.ToString());
          
              s = new V1Status() { Status = "Failure", Reason = "BombExploded" };
              Assert.Equal("BombExploded", s.ToString());
          
              s = new V1Status() { Status = "Failure", Message = "Something bad happened." };
              Assert.Equal("Something bad happened.", s.ToString());
          
              s = new V1Status() { Status = "Failure", Code = 400 };
              Assert.Equal("BadRequest", s.ToString());
          
              s = new V1Status() { Status = "Failure", Code = 911 };
              Assert.Equal("911", s.ToString());
          
              s = new V1Status() { Status = "Failure", Code = 400, Message = "It's all messed up." };
              Assert.Equal("BadRequest - It's all messed up.", s.ToString());
          
              s = new V1Status()
              {
                  Status = "Failure",
                  Code = 400,
                  Reason = "IllegalValue",
                  Message = "You're breaking the LAW!",
              };
              Assert.Equal("IllegalValue - You're breaking the LAW!", s.ToString());
          }
          

Logging Tests

The tests/KubernetesClient.Tests/Logging folder contains tests related to the library’s logging functionalities. Examples include:

  • TestOutputLogger: Writes log messages to the output of the current XUnit test.
  • TestOutputLoggerProvider: Provides a logger provider for logging to XUnit test output.
  • TestOutputLoggingExtensions: Offers extension methods for logging to XUnit test output.

Watch Tests

The tests/KubernetesClient.Tests/WatchTests.cs file contains tests for the watch functionality.

using k8s.Models;
          using k8s.Tests.Mock;
          using Microsoft.AspNetCore.Http;
          using Nito.AsyncEx;
          using System;
          using System.Collections.Generic;
          using System.IO;
          using System.Linq;
          using System.Net;
          using System.Net.Http;
          using System.Text;
          using System.Threading;
          using System.Threading.Tasks;
          using Xunit;
          using Xunit.Abstractions;
          
          namespace k8s.Tests
          {
              public class WatchTests
              {
                  private static readonly string MockAddedEventStreamLine = BuildWatchEventStreamLine(WatchEventType.Added);
                  private static readonly string MockDeletedStreamLine = BuildWatchEventStreamLine(WatchEventType.Deleted);
                  private static readonly string MockModifiedStreamLine = BuildWatchEventStreamLine(WatchEventType.Modified);
                  private static readonly string MockErrorStreamLine = BuildWatchEventStreamLine(WatchEventType.Error);
                  private const string MockBadStreamLine = "bad json";
                  private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(150);
          
                  private readonly ITestOutputHelper testOutput;
          
                  public WatchTests(ITestOutputHelper testOutput)
                  {
                      this.testOutput = testOutput;
                  }
          
                  // ...
          
                  errors += 1;
                                  eventsReceived.Signal();
                              },
                              onClosed: connectionClosed.Set);
          
                          // wait server yields all events
                          await Task.WhenAny(eventsReceived.WaitAsync(), Task.Delay(TestTimeout)).ConfigureAwait(true);
          
                          Assert.True(
                              eventsReceived.CurrentCount == 0,
                              "Timed out waiting for all events / errors to be received.");
          
                          Assert.Contains(WatchEventType.Added, events);
                          Assert.Contains(WatchEventType.Deleted, events);
                          Assert.Contains(WatchEventType.Modified, events);
                          Assert.Contains(WatchEventType.Error, events);
          
                          Assert.Equal(0, errors);
          
                          Assert.True(watcher.Watching);
          
                          serverShutdown.Set();
          
                          // ...
          
                          server.Dispose();
                      }
                  }
          
                  // ...
              }
          }
          

E2E Tests

The tests/E2E.Tests folder contains end-to-end tests that verify the library’s functionality in a real Kubernetes environment.

E2E AOT Tests

The tests/E2E.Aot.Tests folder contains end-to-end tests that are specifically designed for testing the library in an Ahead-Of-Time (AOT) compiled environment.

Simple Tests

The tests/KubernetesClient.Classic.Tests/SimpleTests.cs file demonstrates basic tests for simple functionalities of the Kubernetes client library.

using k8s.Models;
          using System.IO;
          using System.Net;
          using System.Net.Sockets;
          using System.Threading.Tasks;
          using Xunit;
          
          namespace k8s.tests;
          
          // ...
          

Top-Level Directory Explanations

.devcontainer/ - This directory contains files for developing and running the project in a container using Visual Studio Code’s Remote-Containers extension.

doc/ - This directory contains documentation for the project.

examples/ - This directory contains example projects and usage scenarios for the Kubernetes client library.

examples/metrics/ - This subdirectory contains examples of working with metrics in Kubernetes.

examples/patch/ - This subdirectory contains examples of patching Kubernetes resources.

examples/watch/ - This subdirectory contains examples of watching Kubernetes resources for changes.

examples/webApiDependencyInjection/ - This subdirectory contains an example of using dependency injection in a web API using the Kubernetes client library.

examples/workerServiceDependencyInjection/ - This subdirectory contains an example of using dependency injection in a worker service using the Kubernetes client library.

src/ - This directory contains the source code for the project.

src/KubernetesClient/ - This subdirectory contains the main Kubernetes client library source code.

src/LibKubernetesGenerator/ - This subdirectory contains code for generating C# code from OpenAPI definitions.

tests/ - This directory contains test code for the project.

tests/E2E.Aot.Tests/ - This subdirectory contains end-to-end tests for the AOT compiled code.

tests/E2E.Tests/ - This subdirectory contains end-to-end tests for the non-AOT code.

tests/Kubectl.Tests/ - This subdirectory contains tests for the kubectl functionality.

tests/KubernetesClient.Classic.Tests/ - This subdirectory contains tests for the classic implementation of the Kubernetes client library.

tests/KubernetesClient.Tests/ - This subdirectory contains tests for the main implementation of the Kubernetes client library.

tests/KubernetesClient.Tests/assets/ - This subdirectory contains test assets.

tests/KubernetesClient.Tests/LeaderElection/ - This subdirectory contains tests for the leader election functionality.

tests/KubernetesClient.Tests/Logging/ - This subdirectory contains tests for the logging functionality.

tests/KubernetesClient.Tests/Mock/ - This subdirectory contains tests using mocks.

tests/SkipTestLogger/ - This subdirectory contains a test logger implementation that skips logging.