This is a fun session as I have already had about an hour-long conversation with Gil about this very topic for the next The Testing Show (hopefully to be out shortly :) ). Testability is also a bit of a pet topic of mine so it's really cool to hear Gil talking about this directly.
Testability is often of those areas that can be hard to implement late in the game but is much easier to deal with earlier in the process. It's not a common topic in development circles or at least that may seem to be the case. Sure, developers are encouraged (and in many cases required) to work on unit tests. However, unit testing does not translate to overall testability. Testability is putting hooks or developing a product to be able to actually be easier to share information in ways that can help a tester make a decision as to a feature's genuine fitness for use.
Another challenge we all face is the fact that developers are not interchangeable. What one developer does that may be beneficial may be totally outside the wheelhouse of another developer. Additionally, one developer may do very well in delivering their pieces of code but struggle to integrate with other components. Testers can often help fill in the blanks but often we run into places where a system that has been developed is frustratingly opaque. Often it takes for granted we will be looking at an application with a UI. Many of those interactions, to actually look at the workflows in question, may require the user to set up their tests to interact with the UI multiple times just to get to a place that's useful.
An area that Gil and I agree on is the fact that testers if they want to advocate for testability, need to at least have a working knowledge of and the ability to scan and read code. Not necessarily writing code at a developer level but having enough proficiency to read code and get the gist of what's happening can be very helpful. Let's take a classic example, look at the error handling code and see what error messages have been coded in. Can you surface those messages? What would it take to do so? In this circumstance, I'd probably sit down and see if I could surface each of those messages at least once. If I can't do so, I would then get back with the developer and say "what will it take to surface this?" In some cases, it's Oh, right, you need to configure this or do it this way" but sometimes we've been able to prove we can't really get there. These are examples where, if there were API hooks that we could interact with, we could more easily determine if they could be properly surfaced or if they were perhaps not necessary.
One of the other areas Gil points to as frustrating both from a Development and testing standpoint is code duplication. There's of course refactoring to remove used code in places but that duplicate code doesn't just end up being a drag on development. IT can also stymie testing efforts because we may think we have a fix in one place only to discover another place is still broken because the code that got fixed on one place didn't get fixed here. This isn't as simple as adding a hook or putting an API call in but it's definitely a testability issue that needs to be discussed.
The key point Gil is making is the fact that we should make our interactions public. Specifically, we should have an API that we can use for testing purposes and also for active production uses for those who want to do it. "But what if people call those APIs after we ship?!" Well, what about it? If exposing something via an API literally breaks your application, how robust is your original design? More to the point, does the risk of exposing elements and methods outweigh the benefits of easier testability and potentially more usability for the customers? I can't answer that for everyone but from personal experience, making items available in the API and adding testability hooks has not come back to bite us later. In fact, it has actually benefitted us overall by giving our users other options they can use to complete their workflows, in some cases not even interacting with the application at all.
The key takeaway here, IMO, is that we as testers can absolutely influence this conversation and the earlier we get involved in this conversation (And encourage mocking, API calls, dependency injections, etc.) can help us test better and more comprehensively. The critical element, though is that we need to be involved in this process early/ The sooner we can get into a story being developed, the more likely we can have a positive effect on testability. The longer we wait, the more resistant the process of testability will become, not just from the developer's perspective but from the literal code perespective ;).