Your question embeds some false assumptions about the linear nature of testing within an agile process. A mature agile team with cross-functional skill sets treats development and testing as intertwined activities rather than as sequential ones.
You should strive to integrate development and testing so that they are not fundamentally separate work streams. Failing that, you must formally accept the risks and process deficits associated with the currently implemented workflow.
QA Must be Embedded, Not a Separate Process Track
Typically for a team of 3 to 4 developers, there would be 1 QA resource. What are the developers expected to do when QA is happening. Since the number of developers is much more than the QA, bug fixes get done very quick and developers are left with nothing to do towards the end of the sprint.
You are not doing Scrum, you are doing waterfall. Activities should be cross-functional, and leverage a multifaceted team approach to all tasks.
As one example, testers and developers should be working in lockstep throughout a Sprint. Testers should be involved early and often, helping the developers design testable features by working on test criteria from the beginning before a single line of code is written, and helping to ensure that tests are written first.
The QA folks should be running continuous integration every single day, so that there's a tight (and ideally immediate) feedback loop between development and testing. By working with the developers, rather than being treated as a separate follow-on activity, QA becomes an intrinsic part of the design and development cycles rather than an externality.
Developers and QA Should Partner for Testing
What are the developers expected to do when QA is happening. Since the number of developers is much more than the QA, bug fixes get done very quick and developers are left with nothing to do towards the end of the sprint.
Just as testers are expected to be involved with the developers from day one, developers are expected to work with QA during testing tasks. Rather than tossing code over the wall to testers, developers and testers should work together on the testing process so that bugs are fixed as they are discovered.
Imagine a pair-programming scenario where a tester and a developer work together on a test suite. Instead of a developer dumping a wall of code on the tester and then waiting for results, the two might work together on tests and refactorings. For example:
- QA: The X widget failed the embiggening test.
- DEV: Oops. Okay, I'll refactor the embiggener class while you test the end-user insult generator.
- QA: Will do. Oh, look, the insult generator passed!
- DEV: Great! While you were working on that, I widened the embiggener. Try it again.
- QA: It's embiggening properly now. Let's move on to the next set of specs together!
When All Else Fails, Shine a Light on Dysfunctional Process
If for some reason your team can't or won't cooperatively swarm over test-related activities, then the process must make that cost visible to the team. If developers and QA insist on playing volleyball with tasks by tossing things back and forth over a net instead of integrating to perform the work together, then you simply make that (potentially dysfunctional) process fully visible.
Do testers really have nothing to do during the first phase of a Sprint? No, but if that's your process then you acknowledge that having testers idling on the team for half a Sprint is one of the costs of doing business. Likewise, if developers really have nothing at all to contribute to the testing process in the latter half of a Sprint, then you explicitly acknowledge that your developers are getting paid to hang out on Facebook for 50% of the time, and can accept that as a cost of doing business within your chosen process.
Healthy teams treat all members as cross-functional resources, with value to add during each step of the process. Even if you choose not to fully integrate testing as a first-class activity within your Sprints, testers and developers can take turns assisting each other on current tasks. For example, during development a tester can work collaboratively to design test fixtures while the developer is writing the feature; then during testing, the developer might run code coverage analysis or work on converting test results into documentation while the tester runs the tests.
If the team can't or won't work cooperatively in this way, then the organization can simply accept the fact that some roles within the team will be idle at certain points in the process. While not ideal, it might be politically necessary to simply acknowledge that 50% of your roles will be idle at any given time, and that this is an acceptable cost of doing business within your current development process. While I personally consider this a sub-optimal option, it is still better than falling prey to the 100% utilization fallacy that tries to keep everyone looking busy even when doing so is wasteful and generates no value...and sometimes may even actively reduce productivity.