skUnit 0.34.0-beta
dotnet add package skUnit --version 0.34.0-beta
NuGet\Install-Package skUnit -Version 0.34.0-beta
<PackageReference Include="skUnit" Version="0.34.0-beta" />
paket add skUnit --version 0.34.0-beta
#r "nuget: skUnit, 0.34.0-beta"
// Install skUnit as a Cake Addin #addin nuget:?package=skUnit&version=0.34.0-beta&prerelease // Install skUnit as a Cake Tool #tool nuget:?package=skUnit&version=0.34.0-beta&prerelease
skUnit
skUnit is a testing tool for SemanticKernel units, such as plugin functions, kernels, chat services and ...
For example, you can use skUnit to test a GetSentiment
function that analyzes a text and returns its sentiment, such as "Happy" or "Sad".
You can write different scenarios to check how the function behaves with various inputs, such as:
## PARAMETER input
Such a beautiful day it is
## ANSWER Equals
Happy
This scenario verifies that the function returns "Happy" when the input is "Such a beautiful day it is".
This is an Invocation Scenario, which tests a single function call. You can also write Chat Scenarios, which test a sequence of interactions between the user and the SemanticKernel.
Chat Scenarios
A chat scenario is a way of testing how SemanticKernel units, such as plugin functions and kernels, respond to user inputs in skUnit. A chat scenario consists of one or more sub-scenarios, each representing a dialogue turn between the user and the agent.
Example
This is an example of a chat scenario with two sub-scenarios:
# SCENARIO Height Discussion
## [USER]
Is Eiffel tall?
## [AGENT]
Yes it is
### CHECK SemanticCondition
It agrees that the Eiffel Tower is tall or expresses a positive sentiment.
## [USER]
What about Everest Mountain?
## [AGENT]
Yes it is tall too
### CHECK SemanticCondition
It agrees that Everest mountain is tall or expresses a positive sentiment.
Sub-scenario 1
The first sub-scenario tests how the agent responds to the question Is Eiffel tall?
.
The expected answer is something like Yes it is
, but this is not an exact match. It is just a guideline for the desired response.
When the scenario is executed, the OpenAI generates an actual answer, such as Yes it is quite tall.
.
The next statement CHECK SemanticCondition
is an assertion that verifies if the actual answer meets the specified condition:
It agrees that the Eiffel Tower is tall or expresses a positive sentiment.
Sub-scenario 2
The second sub-scenario tests how the agent responds to the follow-up question What about Everest mountain?
.
The expected answer is something like Yes it is tall too
, but again, this is not an exact match. It is just a guideline for the desired response.
When the scenario is executed, the OpenAI generates an actual answer, such as Yes it is very tall indeed.
.
The next statement CHECK SemanticCondition
is an assertion that verifies if the actual answer meets the specified condition:
It agrees that Everest mountain is tall or expresses a positive sentiment.
As you can see, this sub-scenario does not depend on the exact wording of the previous answer. It assumes that the agent responded in the expected way and continues the test. This makes writing long tests easier, as you can rely on the agent's answers to design your test. Otherwise, you would have to account for different variations of the intermediate answers every time you run the test.
However, SemanticSimilar
is not the only assertion method. There are many more assertion checks available (like SemanticCondition, Equals).
You can see the full list of CHECK statements here: CHECK Statement spec.
Scenarios are Valid Markdowns
One of the benefits of skUnit scenarios is that they are valid Markdown files, which makes them very readable and easy to edit.
skUnit scenarios are valid Markdown files, which makes them very readable and easy to edit.
For example, you can see how clear and simple this scenario is: Chatting about Eiffel height
Executing a Test Using a Scenario
Executing tests is a straightforward process. You have the flexibility to utilize any preferred test frameworks such as xUnit, nUnit, or MSTest. With just two lines of code, you can load and run a test:
var markdown = // Load it from .md file
var scenarios = await ChatScenario.LoadFromText(markdown);
await ScenarioAssert.PassAsync(scenarios,
getAnswerFunc: async history =>
{
var result = // your logic to be tested;
return result;
});
The test output will be generated incrementally, line by line:
# SCENARIO Height Discussion
## [USER]
Is Eiffel tall?
## [EXPECTED ANSWER]
Yes it is
### [ACTUAL ANSWER]
Yes, the Eiffel Tower in Paris, France, is tall at 330 meters (1,083 feet) in height.
### CHECK Condition
Confirms that the Eiffel Tower is tall or expresses positivity.
✅ OK
## [USER]
What about Everest Mountain?
## [EXPECTED ANSWER]
Yes it is tall too
### [ACTUAL ANSWER]
Yes, Mount Everest is the tallest mountain in the world, with a peak that reaches 29,032 feet (8,849 meters) above sea level.
### CHECK Condition
The sentence is positive.
✅ OK
## [USER]
What about a mouse?
## [EXPECTED ANSWER]
No, it is not tall.
### [ACTUAL ANSWER]
No, a mouse is not tall.
### CHECK Condition
The sentence is negative.
✅ OK
## [USER]
Give me a JSON containing the Eiffel height.
Example:
{
"height": "330 meters"
}
## [EXPECTED ANSWER]
{
"height": "330 meters"
}
### [ACTUAL ANSWER]
{
"height": "330 meters"
}
### CHECK JsonCheck
{
"height": ["NotEmpty", ""]
}
✅ OK
### CHECK JsonCheck
{
"height": ["Contain", "meters"]
}
✅ OK
This output is generated line by line as the test is executed:
Documents
To better understand skUnit, Check these documents:
- Invocation Scenario Spec: The details of writing an InvocationScenario.
- Chat Scenario Spec: The details of writing an ChatScenario.
- CHECK Statement Spec: The various
CHECK
statements that you can use for assertion.
Requirements
- .NET 7.0 or higher
- An OpenAI API key
Installation
You can easily add skUnit to your project as it is available as a NuGet package. To install it, execute the following command in your terminal:
dotnet add package skUnit
Afterwards, you'll need to instantiate the SemanticKernelAssert
class in your test constructor. This requires passing your OpenAI subscription details as parameters:
public class MyTest
{
SemanticAssert SemanticAssert { get; set; }
MyTest(ITestOutputHelper output)
{
SemanticAssert = new SemanticAssert(_deploymentName, _endpoint, _apiKey, output.WriteLine);
}
[Fact]
TestChat()
{
var scenario = // Load your markdown.
var scenarios = await ChatScenario.LoadFromTest(scenario);
await SemanticAssert.PassAsync(scenarios, async history =>
{
var result = // your logic to be tested;
return result;
});
}
}
And that's all there is to it! 😊
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- Azure.AI.OpenAI (>= 2.1.0-beta.2)
- Markdig (>= 0.38.0)
- Microsoft.SemanticKernel (>= 1.30.0)
- SemanticValidation (>= 0.15.0-beta)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on skUnit:
Repository | Stars |
---|---|
mehrandvd/skunit
skUnit is a testing tool for SemanticKernel units, such as plugin functions and kernels.
|
Version | Downloads | Last updated |
---|---|---|
0.34.0-beta | 43 | 11/26/2024 |
0.33.0-beta | 81 | 10/20/2024 |
0.32.0-beta | 57 | 9/15/2024 |
0.31.0-beta | 53 | 9/14/2024 |
0.30.0-beta | 55 | 9/14/2024 |
0.29.0-beta | 150 | 1/4/2024 |
0.28.0-beta | 73 | 1/2/2024 |
0.27.0-beta | 109 | 1/2/2024 |
0.26.0-beta | 74 | 1/2/2024 |
0.25.0-beta | 89 | 12/30/2023 |
0.24.0-beta | 74 | 12/29/2023 |
0.23.0-beta | 80 | 12/28/2023 |
0.22.0-beta | 77 | 12/28/2023 |
0.21.0-beta | 65 | 12/28/2023 |
0.20.0-beta | 84 | 12/28/2023 |
0.19.0-beta | 63 | 12/27/2023 |
0.18.0-beta | 73 | 12/27/2023 |
0.16.0-beta | 64 | 12/27/2023 |
0.15.0-beta | 81 | 12/27/2023 |
0.14.0-beta | 78 | 12/26/2023 |
0.13.0-beta | 73 | 12/26/2023 |
0.12.0-beta | 74 | 12/26/2023 |
0.11.0-beta | 77 | 12/26/2023 |
0.10.0-beta | 73 | 12/25/2023 |
0.9.0-beta | 79 | 12/25/2023 |
0.8.0-beta | 74 | 12/25/2023 |
0.7.0-beta | 75 | 12/25/2023 |
0.6.0-beta | 76 | 12/25/2023 |
0.5.0-beta | 69 | 12/24/2023 |
0.4.0-beta | 67 | 12/24/2023 |
0.3.0-beta | 77 | 12/24/2023 |
0.1.0-beta | 72 | 12/24/2023 |