microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
library/qtest/src/Functions.qs
101lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | import Util.TestCaseResult, Util.OutputMessage; |
| 5 | import 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, () -> 'T, 'T)`, where |
| 16 | /// the first String is the name of the test, the function is the test case itself, and the |
| 17 | /// final element of the tuple is the expected return value from the test case. |
| 18 | /// |
| 19 | /// # Example |
| 20 | /// ```qsharp |
| 21 | /// CheckAllTestCases([("Should return 42", () -> 42, 42)]); |
| 22 | /// ``` |
| 23 | function CheckAllTestCases<'T : Eq + Show>(test_cases : (String, () -> 'T, 'T)[]) : Bool { |
| 24 | let test_results = RunAllTestCases(test_cases); |
| 25 | |
| 26 | OutputMessage(test_results); |
| 27 | All(test_case -> test_case.did_pass, test_results) |
| 28 | } |
| 29 | |
| 30 | /// # Summary |
| 31 | /// Runs all given test cases and returns a `TestCaseResult` for each test, representing whether or not it passed |
| 32 | /// and what the failure message, if any. |
| 33 | /// This is a good alternative to `CheckAllTestCases` when you want custom output based on the results of your tests, |
| 34 | /// or more control over how test results are rendered. |
| 35 | /// # Input |
| 36 | /// Takes a list of test cases. A test case is a tuple of `(String, () -> 'T, 'T)`, where |
| 37 | /// the first String is the name of the test, the function is the test case itself, and the |
| 38 | /// final element of the tuple is the expected return value from the test case. |
| 39 | /// |
| 40 | /// # Example |
| 41 | /// ```qsharp |
| 42 | /// RunAllTestCases([("Should return 42", () -> 42, 42)]); |
| 43 | /// ``` |
| 44 | function RunAllTestCases<'T : Eq + Show>(test_cases : (String, () -> 'T, 'T)[]) : TestCaseResult[] { |
| 45 | let num_tests = Length(test_cases); |
| 46 | |
| 47 | Mapped((name, case, result) -> TestCase(name, case, result), test_cases) |
| 48 | } |
| 49 | |
| 50 | /// # Summary |
| 51 | /// Given a function to test, an array of test cases of the form (input, expected_output), and a test mode, runs the test cases and returns the result of the test mode. |
| 52 | /// |
| 53 | /// # Inputs |
| 54 | /// - `test_suite_name` : A string representing the name of the test suite. |
| 55 | /// - `func` : The function to test. |
| 56 | /// - `test_cases` : An array of tuples of the form (input, expected_output). |
| 57 | /// - `mode` : A function that takes an array of tuples of the form (test_name, test_case, expected_output) and returns a value of type 'U. |
| 58 | /// Intended to be either `Qtest.Functions.CheckAllTestCases` or `Qtest.Functions.RunAllTestCases`. |
| 59 | /// |
| 60 | /// # Example |
| 61 | /// ```qsharp |
| 62 | /// TestMatrix("Add One", x -> x + 1, [(2, 3), (3, 4)], CheckAllTestCases); |
| 63 | /// ``` |
| 64 | |
| 65 | function TestMatrix<'T, 'O : Show + Eq, 'U>( |
| 66 | test_suite_name : String, |
| 67 | func : 'T -> 'O, |
| 68 | test_cases : ('T, 'O)[], |
| 69 | mode : ((String, () -> 'O, 'O)[]) -> 'U |
| 70 | ) : 'U { |
| 71 | let test_cases_qs = Mapped((ix, (input, expected)) -> (test_suite_name + $" {ix + 1}", () -> func(input), expected), Enumerated(test_cases)); |
| 72 | mode(test_cases_qs) |
| 73 | } |
| 74 | |
| 75 | function RunTestMatrix<'T : Show, 'O : Show + Eq>( |
| 76 | test_suite_name : String, |
| 77 | func : 'T -> 'O, |
| 78 | test_cases : ('T, 'O)[] |
| 79 | ) : TestCaseResult[] { |
| 80 | TestMatrix(test_suite_name, func, test_cases, RunAllTestCases) |
| 81 | } |
| 82 | |
| 83 | function CheckTestMatrix<'T : Show, 'O : Show + Eq>( |
| 84 | test_suite_name : String, |
| 85 | func : 'T -> 'O, |
| 86 | test_cases : ('T, 'O)[] |
| 87 | ) : Bool { |
| 88 | TestMatrix(test_suite_name, func, test_cases, CheckAllTestCases) |
| 89 | } |
| 90 | |
| 91 | /// Internal (non-exported) helper function. Runs a test case and produces a `TestCaseResult` |
| 92 | function TestCase<'T : Eq + Show>(name : String, test_case : () -> 'T, expected : 'T) : TestCaseResult { |
| 93 | let result = test_case(); |
| 94 | if result == expected { |
| 95 | new TestCaseResult { did_pass = true, message = "" } |
| 96 | } else { |
| 97 | new TestCaseResult { did_pass = false, message = $"{name}: expected: {expected}, got: {result}" } |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | export CheckAllTestCases, RunAllTestCases, TestMatrix, RunTestMatrix, CheckTestMatrix; |
| 102 | |