I disagree with @Anusha that building this nested query structure is "complicated". Just build out from the innermost subquery using query builder methods, and insert the built query into its parent query as needed.
Instead of merely converting your posted SQL to query builder calls, I recommend tweaking your SQL to avoid subqueries in a SELECT clause -- these tend to be poor performers.
I recommend JOINing a subquery which groups test cases by id and returns there latest execution date, then JOIN executions table to that derived table to be able to access the last_status of each test_case, filter them by the passed-in status, and count the total.
public function countTestCasesByStatus(string $status): int
{
$latestExecutionPerId = $this->db
->select('tc.id, MAX(tce.execution_date) last_execution_date')
->join('test_case_executions tce1', 'tc.id = tce.test_case_id')
->group_by('tc.id')
->get_compiled_select('test_cases tc');
return $this->db
->join('test_case_executions tce2', 'lepi.id = tce2.test_case_id AND lepi.last_execution_date = tce2.execution_date')
->where('tce2.status', $status)
->count_all_results("($latestExecutionPerId) lepi");
}
Rendered SQL (assuming the input string is foo):
SELECT COUNT(*) AS `numrows`
FROM (
SELECT `tc`.`id`, MAX(tce.execution_date) last_execution_date
FROM `test_cases` `tc`
JOIN `test_case_executions` `tce1` ON `tc`.`id` = `tce`.`test_case_id`
GROUP BY `tc`.`id`
) lepi
JOIN `test_case_executions` `tce2` ON `lepi`.`id` = `tce2`.`test_case_id` AND `lepi`.`last_execution_date` = `tce2`.`execution_date`
WHERE `tce2`.`status` = 'foo'