Hi @PaulCluver
Welcome to the community forum 
This might seem a bit counterintuitive, at least it is for me. My mind associates ✓ with pass and “good”, and ✗ with fail and “not good”.
However, the http_req_failed is a rate that keeps track of the failures. And in the above output, the passes is the number of times it finds a failure.
If you run a test that returns a 200:
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
http.get('https://httpbin.test.k6.io/status/200');
sleep(1);
}
You get 0% failures in the rate, and 0 “passes”, 1 “fails”:
http_req_failed................: 0.00% ✓ 0 ✗ 1
And if you run a test that returns a 500:
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
http.get('https://httpbin.test.k6.io/status/500');
sleep(1);
}
You get 100% failure rate, and 1 “passes”, 0 “fails”:
http_req_failed............: 100.00% ✓ 1 ✗ 0
The JSON reflects the same structure, and as such, you would have to look at the rate value of http_req_failed, which in your case is already 0% (71 requests, all with 200 status code). And if you are looking at the concrete number of requests that did not return 200, those are in the passes value.
This metric was discussed further in https://github.com/grafana/k6/issues/1828, and I’ve opened a doc issue to review if we can better document this: Review if we can document http_req_failed pass/fail values · Issue #1185 · grafana/k6-docs · GitHub.
I hope this helps.
Cheers!