First of all, developers to testers is a good rule of thumb, but it's a bad rule.
What you need to consider is how many use case your application has. Applications which will be interacted with by users in an uncontrolled manner (I.E. web applications or desktop applications) will require more testers than a similar console application.
An application that takes a single file and detects regex patterns in it will require fewer testers than a new OS.
While those are general maxims, the practical advice would be to use some sort of approximate formula based on these factors
1) How many (compartmentalized) use cases are there?
I say compartmentalized use cases because if you include state changes and persistent variables, then seemingly unrelated parts of a program can turn out to be related.
I.E. 2 + 2 = 4 (1 use case) 2 * 2 = 4 (2nd use case). That's two simple operators so, two classes of use cases. However, if you can add
then multiply
, then you can't check ONLY add
and multiply
individually, you must check them in all their possible permutations.
When examining the number of use cases, make sure you include the use cases that involve chaining of commands.
2) How long does it take to test each one?
This doesn't mean (to extend the calculator metaphor) only adding 2 + 2 and looking at the answer. You must include the time it takes to recover from a crash. If the answer is incorrect, you would expect the tester to log the bug with a screenshot and specific instructions on how to recreate the bug. If you don't give them time for this kind of administrating work, then you are baking into your plan the assumption that you have no bugs. And if we're assuming that, then why have testers at all ;)
A complex project will have both a high number of use cases, and a high number of developers, but they are not a guaranteed correlation. You are better off examining your use cases thoroughly and making an educated decision about how many testers will be required.
Added Bonus. Once you've broken down the application so thoroughly, you might find some use cases that were never considered in the design phase, and fix them before a tester finds them.