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
250
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
猫と暮らす Google Nest Cam生活🐈 / WebRTC with Google Nest Cam
yutailang0119
0
210
Apple Vision Pro購入RTA 1泊3日弾丸ハワイツアー / RTA: Purchase Apple Vision Pro in Hawaii
yutailang0119
0
1.4k
個人開発のたのしみ / Enjoying personal development
yutailang0119
0
1k
バックポートして学ぶ新APIの仕組み
yutailang0119
0
2.9k
Backport AsyncImage
yutailang0119
0
740
xcrun Essentials
yutailang0119
6
1.3k
Let's Coding SwiftUI on iPad!
yutailang0119
1
530
Property Wrapperで遊ぼう / Play with Property Wrapper
yutailang0119
2
330
Back of First Screen AB test of Hatena Bookmark iOS app with Firebase AB Testing
yutailang0119
0
320
Other Decks in Technology
See All in Technology
なぜスクラムはこうなったのか?歴史が教えてくれたこと/Shall we explore the roots of Scrum
sanogemaru
5
1.6k
初めてAWSを使うときのセキュリティ覚書〜初心者支部編〜
cmusudakeisuke
1
240
BPaaSにおける人と協働する前提のAIエージェント-AWS登壇資料
kentarofujii
0
140
開発者を支える Internal Developer Portal のイマとコレカラ / To-day and To-morrow of Internal Developer Portals: Supporting Developers
aoto
PRO
1
460
CDK CLIで使ってたあの機能、CDK Toolkit Libraryではどうやるの?
smt7174
4
160
Generative AI Japan 第一回生成AI実践研究会「AI駆動開発の現在地──ブレイクスルーの鍵を握るのはデータ領域」
shisyu_gaku
0
160
複数サービスを支えるマルチテナント型Batch MLプラットフォーム
lycorptech_jp
PRO
0
330
なぜテストマネージャの視点が 必要なのか? 〜 一歩先へ進むために 〜
moritamasami
0
220
Snowflakeの生成AI機能を活用したデータ分析アプリの作成 〜Cortex AnalystとCortex Searchの活用とStreamlitアプリでの利用〜
nayuts
1
480
生成AIでセキュリティ運用を効率化する話
sakaitakeshi
0
670
Android Audio: Beyond Winning On It
atsushieno
0
110
Language Update: Java
skrb
2
290
Featured
See All Featured
GraphQLとの向き合い方2022年版
quramy
49
14k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Git: the NoSQL Database
bkeepers
PRO
431
66k
The Cost Of JavaScript in 2023
addyosmani
53
8.9k
GraphQLの誤解/rethinking-graphql
sonatard
72
11k
Designing for humans not robots
tammielis
253
25k
Optimising Largest Contentful Paint
csswizardry
37
3.4k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
15k
Java REST API Framework Comparison - PWX 2021
mraible
33
8.8k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
9
810
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Facilitating Awesome Meetings
lara
55
6.5k
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