Yes, `@testable` does exactly that. It basically treats the imported module as being part of the module it’s being imported into and gives the type all of the same access levels. So I’d be able to override a method that is *not* marked as open with no issues.
I see nothing in the proposal that restricts a class within the same module from subclassing and overriding `public` methods within the *same* module that it’s defined in.
So you need to have test cases that have *no* `@testable import ModuleToTest` to ensure the API contracts are being tested well. This is John’s point, that proper public API (e.g. “black box”) test cases would alleviate this issue from happening.
-David
···
On Jul 27, 2016, at 8:52 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Wed, Jul 27, 2016 at 10:30 PM, David Owens II via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> On Jul 27, 2016, at 7:18 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:
>
>
>> On Jul 27, 2016, at 6:55 PM, David Owens II via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> Yes, it’s per file. It’s also added in the initial template that Xcode creates with your project. In addition, it’s recommended by many that talk about “how to unit test in Swift.” So, to someone that is not paying scrupulous attention, there is no mechanism to prevent against this today.
>
> Perhaps we're not doing a good job of messaging this.
>
> The Xcode template is the way it is because @testable imports are the right default for a *program* written in Swift. A lot of the code in an application or command-line program isn't really suitable for independent, in-process black-box testing, because it isn't really presenting an integrated API. If you break it down into components that can be independently tested, that's awesome, and at that point you can switch the imports in your tests over to non-@testable. But we don't want the test template to create any obstacles to testing, because as you say, people already don't write enough tests.
My primary concern is that it’s easy to think you’ve done the right thing and push out a release because all of your testing shows it’s good, only to find you messed up in a way that it’s easy for a tool to validate. Writing new code is probably not going to be the primary source of this, but refactoring a `public` class to an `open` one, where there are already existing tests for that class, probably in a single file and using `@testable`, it’s easy to say, “looks good, tests passed, integrations look good.”
If you're refactoring `public` classes into `open` ones, though, you'd be more likely to have forgotten to open a method you intend to make overridable, no? And there's no way to change the rules here to have `@testable` pick that up…
Right. So IIUC, what you called a serious testability issue earlier in the
thread (inadvertent open inside public) is no more and no less an issue
with @testable than inadvertent sealed inside open (in that neither would
be picked up during such testing), and proper black box testing is what you
need to verify that the public API contract is as you intend it to be.
···
On Thu, Jul 28, 2016 at 01:15 David Owens II <david@owensd.io> wrote:
On Jul 27, 2016, at 8:52 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Wed, Jul 27, 2016 at 10:30 PM, David Owens II via swift-evolution < > swift-evolution@swift.org> wrote:
> On Jul 27, 2016, at 7:18 PM, John McCall <rjmccall@apple.com> wrote:
>
>
>> On Jul 27, 2016, at 6:55 PM, David Owens II via swift-evolution < >> swift-evolution@swift.org> wrote:
>>
>> Yes, it’s per file. It’s also added in the initial template that Xcode
creates with your project. In addition, it’s recommended by many that talk
about “how to unit test in Swift.” So, to someone that is not paying
scrupulous attention, there is no mechanism to prevent against this today.
>
> Perhaps we're not doing a good job of messaging this.
>
> The Xcode template is the way it is because @testable imports are the
right default for a *program* written in Swift. A lot of the code in an
application or command-line program isn't really suitable for independent,
in-process black-box testing, because it isn't really presenting an
integrated API. If you break it down into components that can be
independently tested, that's awesome, and at that point you can switch the
imports in your tests over to non-@testable. But we don't want the test
template to create any obstacles to testing, because as you say, people
already don't write enough tests.
My primary concern is that it’s easy to think you’ve done the right thing
and push out a release because all of your testing shows it’s good, only to
find you messed up in a way that it’s easy for a tool to validate. Writing
new code is probably not going to be the primary source of this, but
refactoring a `public` class to an `open` one, where there are already
existing tests for that class, probably in a single file and using
`@testable`, it’s easy to say, “looks good, tests passed, integrations look
good.”
If you're refactoring `public` classes into `open` ones, though, you'd be
more likely to have forgotten to open a method you intend to make
overridable, no? And there's no way to change the rules here to have
`@testable` pick that up…
Yes, `@testable` does exactly that. It basically treats the imported
module as being part of the module it’s being imported into and gives the
type all of the same access levels. So I’d be able to override a method
that is *not* marked as open with no issues.
I see nothing in the proposal that restricts a class within the same
module from subclassing and overriding `public` methods within the *same*
module that it’s defined in.
So you need to have test cases that have *no* `@testable import
ModuleToTest` to ensure the API contracts are being tested well. This is
John’s point, that proper public API (e.g. “black box”) test cases would
alleviate this issue from happening.