microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/add-link-to-qsharp-application

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

library/qtest/src/Operations.qs

141lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4import Util.TestCaseResult, Util.OutputMessage;
5import Std.Arrays.Mapped, Std.Arrays.All, Std.Arrays.Enumerated;
6
7/// # Summary
8/// Runs a number of test cases and returns true if all tests passed, false otherwise.
9/// Prints a report of what passed and what failed as output.
10///
11/// For a more flexible test running function, see `RunAllTestCases` which returns
12/// test results instead of printing out to output.
13///
14/// # Input
15/// Takes a list of test cases. A test case is a tuple of `(String, Int, Qubit[] => Unit, Qubit[] => 'T, 'T)`, where
16/// the first String is the name of the test, the int is the number of qubits to allocate for this test,
17/// the first function is a qubit state prep function to be run before the test, the second function is the test case itself, and the
18/// final element of the tuple is the expected return value from the test case.
19///
20/// # Example
21/// ```qsharp
22/// CheckAllTestCases([("0b0001 == 1", 4, (qs) => X(qs[0]), (qs) => MeasureSignedInteger(qs, 4), 1)]);
23/// ```
24operation CheckAllTestCases<'T : Eq + Show>(test_cases : (String, Int, Qubit[] => (), Qubit[] => 'T, 'T)[]) : Bool {
25 let test_results = RunAllTestCases(test_cases);
26
27 OutputMessage(test_results);
28
29 All(test_case -> test_case.did_pass, test_results)
30}
31
32/// # Summary
33/// Runs all given test cases and returns a `TestCaseResult` for each test, representing whether or not it passed
34/// and what the failure message, if any.
35/// This is a good alternative to `CheckAllTestCases` when you want custom output based on the results of your tests,
36/// or more control over how test results are rendered.
37/// # Input
38/// Takes a list of test cases. A test case is a tuple of `(String, Int, Qubit[] => Unit, Qubit[] => 'T, 'T)`, where
39/// the first String is the name of the test, the Int is the number of qubits, the first operation prepares the state,
40/// the second operation is the test case itself, and the final element is the expected return value.
41///
42/// # Example
43/// ```qsharp
44/// RunAllTestCases([("0b0001 == 1", 4, (qs) => X(qs[0]), (qs) => MeasureSignedInteger(qs, 4), 1)]);
45/// ```
46operation RunAllTestCases<'T : Eq + Show>(test_cases : (String, Int, Qubit[] => Unit, Qubit[] => 'T, 'T)[]) : TestCaseResult[] {
47 MappedOperation((name, num_qubits, prepare_state, case, result) => {
48 use qubits = Qubit[num_qubits];
49 prepare_state(qubits);
50 let res = TestCase(name, qubits, case, result);
51 ResetAll(qubits);
52 res
53 }, test_cases)
54}
55
56/// Helper function, copy of `Std.Arrays.Mapped` which works on operations instead
57/// of functions.
58operation MappedOperation<'T, 'U>(mapper : ('T => 'U), array : 'T[]) : 'U[] {
59 mutable mapped = [];
60 for element in array {
61 set mapped += [mapper(element)];
62 }
63 mapped
64}
65
66
67/// # Summary
68/// Given an operation on some qubits `func` which returns some value to test and a number of qubits to use `num_qubits`,
69/// runs a number of test cases of the form `(Qubit[] => Unit, 'O)` where the first element is a qubit
70/// state preparation operation and the second element is the expected output of the operation.
71/// Returns the result of the `mode` function which takes a list of test cases and returns a value of type `'U`.
72///
73/// # Input
74/// - `test_suite_name` : A string representing the name of the test suite.
75/// - `func` : An operation which takes an array of qubits and returns a value of type `'O`.
76/// - `num_qubits` : The number of qubits to use in the test. These are allocated before the test and reset before each test case.
77/// - `test_cases` : A list of test cases, each of the form `(Qubit[] => Unit, 'O)`. The lambda operation should set up the qubits
78/// in a specific state for `func` to operate on.
79/// - `mode` : A function which takes a list of test cases and returns a value of type `'U`. Intended to be either `Qtest.Operations.CheckAllTestCases` or `Qtest.Operations.RunAllTestCases`.
80///
81/// # Example
82/// ```qsharp
83/// let test_cases: (Qubit[] => Unit, Int)[] = [
84/// (qs => { X(qs[0]); X(qs[3]); }, 0b1001),
85/// (qs => { X(qs[0]); X(qs[1]); }, 0b0011)
86/// ];
87///
88/// let res : Util.TestCaseResult[] = Operations.TestMatrix(
89/// // test name
90/// "QubitTestMatrix",
91/// // operation to test
92/// qs => MeasureInteger(qs),
93/// // number of qubits
94/// 4,
95/// // test cases
96/// test_cases,
97/// // test mode
98/// Operations.RunAllTestCases
99/// );
100/// ```
101
102operation TestMatrix<'O : Show + Eq, 'U>(
103 test_suite_name : String,
104 func : Qubit[] => 'O,
105 num_qubits : Int,
106 test_cases : (Qubit[] => Unit, 'O)[],
107 mode : ((String, Int, Qubit[] => Unit, Qubit[] => 'O, 'O)[]) => 'U
108) : 'U {
109 let test_cases_qs = Mapped((ix, (qubit_prep_function, expected)) -> (test_suite_name + $" {ix + 1}", num_qubits, qubit_prep_function, func, expected), Enumerated(test_cases));
110 mode(test_cases_qs)
111}
112
113operation CheckTestMatrix<'O : Show + Eq>(
114 test_suite_name : String,
115 func : Qubit[] => 'O,
116 num_qubits : Int,
117 test_cases : (Qubit[] => Unit, 'O)[]
118) : Bool {
119 TestMatrix(test_suite_name, func, num_qubits, test_cases, CheckAllTestCases)
120}
121
122operation RunTestMatrix<'O : Show + Eq>(
123 test_suite_name : String,
124 func : Qubit[] => 'O,
125 num_qubits : Int,
126 test_cases : (Qubit[] => Unit, 'O)[]
127) : TestCaseResult[] {
128 TestMatrix(test_suite_name, func, num_qubits, test_cases, RunAllTestCases)
129}
130
131/// Internal (non-exported) helper function. Runs a test case and produces a `TestCaseResult`
132operation TestCase<'T : Eq + Show>(name : String, qubits : Qubit[], test_case : (Qubit[]) => 'T, expected : 'T) : TestCaseResult {
133 let result = test_case(qubits);
134 if result == expected {
135 new TestCaseResult { did_pass = true, message = "" }
136 } else {
137 new TestCaseResult { did_pass = false, message = $"{name}: expected: {expected}, got: {result}" }
138 }
139}
140
141export CheckAllTestCases, RunAllTestCases, TestMatrix, CheckTestMatrix, RunTestMatrix;