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
210
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
Apple Vision Pro購入RTA 1泊3日弾丸ハワイツアー / RTA: Purchase Apple Vision Pro in Hawaii
yutailang0119
0
1.4k
個人開発のたのしみ / Enjoying personal development
yutailang0119
0
990
バックポートして学ぶ新APIの仕組み
yutailang0119
0
2.8k
Backport AsyncImage
yutailang0119
0
710
xcrun Essentials
yutailang0119
6
1.3k
Let's Coding SwiftUI on iPad!
yutailang0119
1
510
Property Wrapperで遊ぼう / Play with Property Wrapper
yutailang0119
2
320
Back of First Screen AB test of Hatena Bookmark iOS app with Firebase AB Testing
yutailang0119
0
310
Lab of WWDC19
yutailang0119
1
520
Other Decks in Technology
See All in Technology
Model Mondays S2E01: Advanced Reasoning
nitya
0
330
新規プロダクト開発、AIでどう変わった? #デザインエンジニアMeetup
bengo4com
0
450
DB 醬,嗨!哪泥嘎斯基?
line_developers_tw
PRO
0
150
AI技術トレンド勉強会 #1MCPの基礎と実務での応用
nisei_k
1
190
kubellが挑むBPaaSにおける、人とAIエージェントによるサービス開発の最前線と技術展望
kubell_hr
1
290
Grafana MCP serverでなんかし隊 / Try Grafana MCP server
kohbis
0
340
脅威をモデリングしてMCPのセキュリティ対策を考えよう
flatt_security
4
1.6k
評価の納得感を2段階高める「構造化フィードバック」
aloerina
1
160
AWS全冠したので振りかえってみる
tajimon
0
140
TODAY 看世界(?) 是我們在看扣啦!
line_developers_tw
PRO
0
160
データ戦略部門 紹介資料
sansan33
PRO
1
3.2k
Long journey of Continuous Delivery at Mercari
hisaharu
1
210
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
107
19k
Product Roadmaps are Hard
iamctodd
PRO
53
11k
Into the Great Unknown - MozCon
thekraken
39
1.8k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
48
5.4k
Stop Working from a Prison Cell
hatefulcrawdad
269
20k
Docker and Python
trallard
44
3.4k
BBQ
matthewcrist
89
9.7k
Agile that works and the tools we love
rasmusluckow
329
21k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Building Applications with DynamoDB
mza
95
6.4k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
16
920
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.3k
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