There are multiple ways to do this, depending on what exactly you want to check.
- Using AllowAtMostNCallsCA library operation.
The easiest way (with the code short enough to be included) is applicable if you know that you only use CCNOT gates when you want a Toffoli gate, and you never use Controlled X gates. In this case you can AllowAtMostNCallsCA operation that enforces exactly that:
namespace Tests {
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
operation op() : Unit {
using (qs = Qubit[3]) {
for (k in 0..10) {
CCNOT(qs[0], qs[1], qs[2]);
}
}
}
@Test("ResourcesEstimator")
operation test_op_toffoli_count_at_most_10() : Unit {
within {
AllowAtMostNCallsCA(10, CCNOT, "Too many Toffolis");
} apply {
op();
}
}
}
This test will fail right away, and that's how you can notice that the loop actually uses 11 CCNOTs. However, if you replace the CCNOTs in the loop body with Controlled X([qs[0], qs[1]], qs[2]);
(which is exactly the same gate), the test will happily pass irrespective of how many times you use the gate.
- Using resource estimator.
You can write a test (it will have to be in a different language, though) that will invoke ResourcesEstimator, run an operation using it, extract the statistics and analyze them. I don't have a ready example on hand; the closest thing is this documentation. This approach has the advantage of matching the resource estimates done by ResourcesEstimator exactly, rather than tracking specific gates.
- Using custom simulator.
If you want to do some sophisticated checks, for example, count all gates that act on exactly 3 qubits and limit their number, you can write your own simulator that would extend the simulator you like by doing some extra counting whenever an operation is called. This simulator could expose access to those statistics to your Q# code, so you could write custom assertions using this data. I'm not including the full code here, since it's pretty lengthy (and you indicated that you don't want to use a second language); you can find a complete example here (some tasks in the Quantum Katas use tests like "prohibit all multi-qubit operations except Measure", so this simulator comes handy).