Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Swiftの “private” を テストする / Testing Swift "private"
Search
Yutaro Muta
February 18, 2025
Technology
0
300
Swiftの “private” を テストする / Testing Swift "private"
Mobile Act OSAKA 15
https://mobileact.connpass.com/event/343364/
Yutaro Muta
February 18, 2025
Tweet
Share
More Decks by Yutaro Muta
See All by Yutaro Muta
Swift Concurrencyでのスケジュール処理を考える / Mobile Act OSAKA 17
yutailang0119
0
110
猫と暮らすネットワークカメラ生活🐈 ~Vision frameworkでペットを愛でよう~ / iOSDC Japan 2025
yutailang0119
0
330
猫と暮らす Google Nest Cam生活🐈 / WebRTC with Google Nest Cam
yutailang0119
0
250
Apple Vision Pro購入RTA 1泊3日弾丸ハワイツアー / RTA: Purchase Apple Vision Pro in Hawaii
yutailang0119
0
1.5k
個人開発のたのしみ / Enjoying personal development
yutailang0119
0
1.1k
バックポートして学ぶ新APIの仕組み
yutailang0119
0
3.1k
Backport AsyncImage
yutailang0119
0
770
xcrun Essentials
yutailang0119
6
1.4k
Let's Coding SwiftUI on iPad!
yutailang0119
1
550
Other Decks in Technology
See All in Technology
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
12k
テストセンター受験、オンライン受験、どっちなんだい?
yama3133
0
210
プロンプトエンジニアリングを超えて:自由と統制のあいだでつくる Platform × Context Engineering
yuriemori
0
350
2025-12-27 Claude CodeでPRレビュー対応を効率化する@機械学習社会実装勉強会第54回
nakamasato
4
1.4k
『君の名は』と聞く君の名は。 / Your name, you who asks for mine.
nttcom
1
150
自己管理型チームと個人のセルフマネジメント 〜モチベーション編〜
kakehashi
PRO
5
2.4k
あの夜、私たちは「人間」に戻った。 ── 災害ユートピア、贈与、そしてアジャイルの再構築 / 20260108 Hiromitsu Akiba
shift_evolve
PRO
0
510
会社紹介資料 / Sansan Company Profile
sansan33
PRO
11
390k
田舎で20年スクラム(後編):一個人が企業で長期戦アジャイルに挑む意味
chinmo
1
1.3k
AI との良い付き合い方を僕らは誰も知らない (WSS 2026 静岡版)
asei
1
270
kintone開発のプラットフォームエンジニアの紹介
cybozuinsideout
PRO
0
470
re:Invent2025 セッションレポ ~Spec-driven development with Kiro~
nrinetcom
PRO
2
170
Featured
See All Featured
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
31
The browser strikes back
jonoalderson
0
300
Between Models and Reality
mayunak
1
160
Side Projects
sachag
455
43k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
0
170
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
35
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
82
BBQ
matthewcrist
89
10k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.3k
Building the Perfect Custom Keyboard
takai
2
670
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Transcript
Swiftの “private” を テストする id:yutailang0119 / @yutailang0119 Mobile Act OSAKA
15 1
Who am I!? • id:yutailang0119 ◦ @yutailang0119 • 株式会社はてな ◦
@京都オフィス ◦ アプリケーションエンジニア ▪ iOS/Android ◦ サービスプラットフォームチーム • try! Swift Tokyo Organizer • AVP座談会 🥽 2
3 Introduction
Introduction • private/fileprivateは、参照範囲を制限 ◦ @testableもアクセスできない ◦ open, package, internalはアクセス可能 •
Javaには @VisibleForTesting がある ◦ https://developer.android.com/reference/androidx/annotation/VisibleForTesting 4
Access Level 5 • open • package • internal •
fileprivate • private https://docs.swift.org/swift-book/documentation/the-swift-programming-language/accesscontrol/
6 Motivation
Motivation • テストのためのinternalを避けたい ◦ e.g.) 🙅 コメントでの規制 VisibleForTesting • アクセスのバイパス手段がほしい
7
8 Proposed solution
9 yutailang0119/swift-bypass-accessing
yutailang0119/swift-bypass-accessing • Swift Macros ◦ @BypassAccess • ___ prefix付きコード生成 PeerMacro
• #if DEBUG & internal 10
PeerMacro @attached(peer, names: prefixed(___), named(___init)) public macro BypassAccess() = #externalMacro(
module: "BypassAccessingMacros", type: "BypassAccessMacro" ) 11
12 Detailed design
Detailed design import BypassAccessing struct Declaration { @BypassAccess private let
property: String = "property" @BypassAccess fileprivate func function() -> String { #function } } 13
Detailed design import Testing import BypassAccessing @testable import Example struct
Tests { @Test func test() { let declaration = Declaration() #if DEBUG #expect(declaration.___property == "property") #expect(declaration.___function() == "function()") #endif } } 14
15 Macro
Macro import BypassAccessing struct Declaration { @BypassAccess private let property:
String = "property" } 16
Expand Macro import BypassAccessing struct Declaration { @BypassAccess private let
property: String = "property" #if DEBUG var ___property: String { property } #endif } 17
Macro import BypassAccessing struct Declaration { @BypassAccess fileprivate func function()
-> String { #function } } 18
Expand Macro import BypassAccessing struct Declaration { @BypassAccess fileprivate func
function() -> String { #function } #if DEBUG func ___function() -> String { function() } #endif } 19
20 Support Grammar
Support Grammar • let • var ◦ Stored ◦ Computed
• func • init 21
Modifier, Accessor • async, @MainActor • throws • static, class
• inout • Generics 22 https://docs.swift.org/swift-book/documentation/the-swift-programming-language/summaryofthegrammar
Modifier, Accessor 23 import BypassAccessing struct Declaration<Element> { @BypassAccess @MainActor
private init(_ arg: inout String) async throws where Element: Equatable {} #if DEBUG @MainActor static func ___init(_ arg: inout String) async throws -> Self where Element: Equatable { try await Self.init(_: &arg) } #endif }
Limitation • ❌ privateが現れるインターフェース ◦ Method must be declared private
because its parameter uses a private type • ❌ 型推論を伴うプロパティ ◦ ◦ '@BypassAccess' attribute require TypeAnnotation 24 @BypassAccess private var value = "value"
Support Grammar • 想定利用ケースは、テストを参照 ◦ https://github.com/yutailang0119/swift-bypass-accessing/tree/main/Tests/BypassAccessingTests • 考慮外パターンが存在しそう🫥 25
小噺 • SwiftSyntaxBuilder ◦ 複雑だが、今回のケースでは便利 ▪ 条件に応じて、Expressionを組み合わせ可能 ◦ PlainTextで実装後、SyntaxBuilderで書き直した •
Macroのテストは swift-testing が使えない ◦ XCTest ◦ https://github.com/swiftlang/swift-syntax/issues/2720 26
27 Conclusion
Conclusion • yutailang0119/swift-bypass-accessing ◦ @BypassAccess • 想定外を見つけたら、ご連絡ください📲 28
29 Advertisement
30
try! Swift Tokyo 2025 • 2025/04/09 - 11 • 立川ステージガーデン
• https://tryswift.jp/ 31
hatena.co.jp/recruit 32 32