Cybozu Inside Out | サイボウズエンジニアのブログ

 

kintone のテストを JUnit 5 に移行した話

こんにちは、kintone 開発チームの @hikoma です。kintone のテストを JUnit 4 から JUnit 5 に移行した話を公開したいと思います。

背景

2017 年に JUnit 5 がリリースされてから約 4 年半、みなさんは既に JUnit 5 を利用していることかと思います。

kintone では JUnit 5 への移行がなかなか進みませんでした。テストのボリュームがそれなりにあり(Java の単体テストが約 6500、REST API のテストが約 4000、Selenium のテストが約 3000)、E2E テストで並列実行やリトライのために JUnit 4 の仕組みを利用していたので、目に見える問題が起きていない状況では優先度も上がりませんでした。

しかし、このような状況ではテストの改善に着手しにくく、持続的な開発のリスクも感じていたため、何度目かの移行にチャレンジしました。

方針

基本的には様々なマイグレーションガイドに従って、粛々とアノテーションを書き換え、TestRule を Extension に書き換えることで JUnit 5 に移行できます。

Maven Surefire Plugin を使っている場合は JUnit 4 と JUnit 5 のテストを同時に動かすことも可能なので、部分的に移行することも可能です。

しかし、後述するように E2E テストでは並列実行の仕組みが大きく変わるため部分的な移行が難しく、単体テストに関しても正規表現での置換で対応できる部分が多かったので部分的な移行のメリットはそこまでありませんでした。部分的に移行すると JUnit 4 と JUnit 5 が混在することによって認知負荷が上がってしまうデメリットもあるので、部分的な移行は選択しませんでした。

そういうわけで、コンフリクトが起きても大丈夫なように、置換用のスクリプトを用意して、適宜コミットを作り直しながら移行を進めていきました。

正規表現での置換

JUnit 4 と JUnit 5 では以下の対応で置き換えしました。

JUnit 4 JUnit 5
org.junit.Test org.junit.jupiter.api.Test
org.junit.Before org.junit.jupiter.api.BeforeEach
org.junit.After org.junit.jupiter.api.AfterEach
org.junit.BeforeClass org.junit.jupiter.api.BeforeAll
org.junit.AfterClass org.junit.jupiter.api.AfterAll
org.junit.Ignore org.junit.jupiter.api.Disabled
org.junit.Assume.* org.junit.jupiter.api.Assumptions.*
Theory ParameterizedTest
Enclosed Nested
SpringJUnit4ClassRunner SpringExtension
MockitoJUnitRunner MockitoExtension

具体的には以下のようなコードで置換します。

REGEX1='s/import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/import org.junit.jupiter.api.extension.ExtendWith;import org.springframework.test.context.junit.jupiter.SpringExtension;/g'
REGEX2='s/\@RunWith\(SpringJUnit4ClassRunner.class\)/\@ExtendWith(SpringExtension.class)/g'

grep -r -l "import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;" src/test/ \
  | xargs perl -i -npe "$REGEX1; $REGEX2;"

置換後は spotless-maven-plugin を使ってコードのフォーマットと不要なインポートを削除しています。基本的にはこの方式で置換できましたが、Theory と Enclosed は単純な置き換えではできない部分も出てきました。

Theory

kintone では @DataPoints をフィールドで利用していましたが、ParameterizedTest ではフィールドをデータソースに利用できません。本来はメソッドに置き換えると良いのですが、ボリュームが多かったので、以下のように fixtureProvider メソッドを追加するように正規表現で置換することで対応しました。

// JUnit 4
    @DataPoints
    public static final Fixture[] fixtures = { ... };

    @Theory
    public void test(Fixture f) {
// JUnit 5
    public static Fixture[] fixtureProvider() {
        return fixtures;
    }

    public static final Fixture[] fixtures = { ... };

    @ParameterizedTest
    @MethodSource("fixtureProvider")
    public void test(Fixture f) {

Enclosed

Enclosed ではネストしたクラスが static でしたが、Nested ではネストしたクラスを static にはできません。

ネストしたクラスの static を外すだけであれば正規表現での置換で対応可能でしたが、@BeforeAll@MethodSource など本来 static である必要があるものをネストしたクラスで使っている場合には、ネストしたクラスに @TestInstance(Lifecycle.PER_CLASS) を付与する必要があります。

さすがに正規表現で @TestInstance(Lifecycle.PER_CLASS) に対応することは難しそうだったので、手動で修正を行い、コミットを作り直す時は cherry-pick して対応しました。

E2E テストの移行

kintone の E2E テストには、Selenium を使ったブラウザテストと、REST API のテストがあります。E2E テストは時間がかかるので、kintone を複数台起動して並列でテストを実行するようにしています。また、E2E テストは不安定なため、失敗時にはリトライする仕組みも用意しています。

並列実行

JUnit 4 では Maven Surefire Plugin の機能(parallel=classes)で並列実行していましたが、JUnit 5 では Parallel Execution 機能を使って並列実行できます。ただし、現時点で最新の Maven Surefire Plugin 3.0.0-M6 では、テスト結果の XML が壊れてしまうので(SUREFIRE-1643)使う際には注意が必要です。

また、Maven Surefire Plugin には統計情報を使って実行順序を並び替える機能がありましたが(runOrder=balanced)、JUnit 5 には対応していないため実装しています。AfterAllCallback で実行時間をログに出力する Extension を実装し、次回の実行時にログを見てクラスを並び替える ClassOrderer を実装することで実現できました。

リトライ

JUnit 4 では TestRule を使って Statement の evaluate を try-catch で囲んでリトライする簡単な実装でしたが、JUnit 5 の Extension ではイベントハンドラを登録するだけで、任意のタイミングでの実行の制御はできなくなっています。

JUnit 5 でリトライを実現するために以下の選択肢を検討しました。

kintone では環境によってリトライ回数を変えたり、トータルのリトライ回数を制限したり、不安定なテストを見つけるためにリトライ数を計測したり、いくつか独自の対応が必要だったので Extension を実装しました。

仕組み的には他のライブラリと同様で、TestTemplate の仕組みを使って実装しています。TestTemplate を使う場合は、他の TestTemplate を使う Extension と相互に連携できない制限があります。例えば ParameterizedTest をリトライするには、ParameterizedTest の機能とリトライの機能を両方持った Extension を実装する必要があります。kintone の E2E ではそこまで ParameterizedTest を使っていなかったので、追加の Extension を実装せずに ParameterizedTest を手動で展開する対応をしました。

マージ!

他にも細かい修正は必要でしたが、上記の対応で一通り移行の目処が立ちました。

ここまではバックログのタスクとしてではなく、個人の探求時間を使って一人で進めてこられましたが、実際にマージするにはコードレビューをしてもらう必要があります。いきなり巨大なプルリクエストのレビューを依頼しても、マージされるまでには時間がかかると思ったので、まずは JUnit 5 移行の勉強会を開きました。

勉強会では JUnit 5 の基本的な使い方の紹介(進藤遼さんのJJUG CCC 2018 Spring の発表を利用させてもらいました)と、今まで書いた内容をもう少し具体的に紹介して、今までの書き方とこれからの書き方を比べながら紹介していきました。

勉強会を開くことで、マージ後に開発者がスムーズに移行できるようになるだけでなく、プルリクエストのレビューに協力してくれるメンバーも3人見つけることができました。勉強会のおかげで、具体的な変更点を理解してもらえたので、レビューもやりやすくなったと思います。全員のスケジュールが合う時間で2〜3時間くらいのコードレビューの会を実施し、再度新しい仕組みの共有、スクリプトとコードのレビュー、不具合や対応漏れの修正を行い、3回目くらいにはマージ可能な状態になりました。移行当日には、他のチームメンバーにマージを控えてもらった状態でコミットを作り直し、3 月に無事にマージができました。

おわりに

この記事では JUnit 4 から JUnit 5 への移行を紹介しました。まだ JUnit 4 を利用している環境がどのくらい残っているのか分かりませんが、何かのお役に立てれば幸いです。

JUnit 5 に移行したことで、テストの改善にも心置きなく手をつけられそうです。この記事ではフロントエンドのテストには触れませんでしたが、現在フロントエンドリアーキテクチャプロジェクトが進んでいて、フロントエンドの単体テストも書きやすくなっていくことかと思います。今後はテストピラミッドの考え方を参考にして E2E ではなく適切なレイヤーでテストを書けるように整備していきたいですね。

 

グループウェアの再定義を一緒にやりませんか

ymmt (@ymmt2005) です。 昨年までは Neco プロジェクトとして自社データセンターを Kubernetes を中心としたシステムに刷新していました。

次の活動として、今度は Identity and Access Management (IAM) 分野に取り組むことにしました。 IAM というのは、複数のサービスを跨いでサインインするシングルサインオン(SSO)や自動的にユーザーを作成・削除するプロビジョニングなどを実現するものです。 代表的な製品としては OktaAzure Active Directory があります。

今回はなぜ IAM 分野に取り組むことにしたのかの背景と、今後の取り組みについてご紹介します。

サイボウズ製品の構成と課題

サイボウズでは約 20 年前の創業時から Web グループウェアを開発し販売しています。 サイボウズ Office および Garoon は元々お客様のサーバーにインストールするタイプの製品として開発されました。 そのため基本的に他のサービスと組み合わせるのではなく、これひとつでチームの情報共有は何でもできる製品として設計されています。

時代は流れて今は各種のクラウドサービスを活用することが一般的になりました。 サイボウズでも cybozu.com として前述の Office, Garoon に加えて Kintone とメールワイズをクラウドで提供しています。

現在のサイボウズ社内では、cybozu.com はもちろん、その他用途に合わせて数百にも及ぶクラウドサービスを使い分けています。 GitHub, Slack, Miro, Zoom などなど。

情報システム管理の点からすると、どの社員にどのサービスを使うように設定するべきかや、入退社の処理が非常に煩雑になっています。 それ以上に問題なのが、当社の製品が他社サービスと組み合わせて使う前提で設計されていない点です。 もちろん連携開発に必要な API は備えていますが、いわゆる OAuth 2.0 をはじめとする標準的な認証認可の仕組みを備えていません。

用途に合わせて様々なクラウドサービスを使い分けること、およびそうした時に発生する問題は当社に限らず昨今多くの企業で課題になっていると思います。

グループウェアを再定義する

好き勝手に様々なクラウドサービスを使うだけでは管理コストが高いですしチームの設定などが共通になりません。 また、情報共有を阻害する結果にもしばしばなります。

このような背景を元に、改めて現代のグループウェアが備えているべき特性を考えてみました。

  • 業務に応じて各種クラウドサービスを自由に使い分けられる
  • ユーザーやチームが可視化され、コミュニケーションが容易に行える
  • 使うツールが違っても情報の共有ができる

具体的には、以下のような機能を中心に据えて、グループウェアの諸機能を再実装していくのが良いと考えます。

  • ユーザー/グループの情報を管理して提供(ディレクトリサービス)
  • OAuth 2.0 の認可サーバーとして各種クラウドサービスとの情報連携をサポート
  • SAML 2.0 や OIDC によるシングルサインオンを提供

冒頭で紹介した「IAM 分野への取り組み」というのは、この機能面を指してのものです。 クラウド時代に合わせたグループウェアコンセプトの刷新が本当にやりたいことなのですが、ちょっと抽象的なので。

一緒にやりませんか

そういうわけで、IAM プロダクトを研究開発するプロジェクトを開始しました。

IAM プロダクトは障害で使えないと大変影響が大きいため、非常に高い稼働率が必要になります。 そのため、今回は技術構成も従来のものに拘らず大胆に見直していきます。

文脈が少し違うのですが、今後のエンジニア採用強化に向けて英語人材によりチームの構成にも取り組みます。

  • 完全に新規の IAM プロダクト開発
  • 英語でのチーム開発
  • グループウェアの再定義

このプロジェクトのエンジニアリングマネージャー @y_okady が Meety をやっていますので、面白そうと思ったらぜひお声がけください。詳しいお話をさせていただきます!

meety.net

また、現在3つのポジションで一緒に働いてくれる仲間を募集しています。たくさんの方のご応募お待ちしております。

cybozu.co.jp

cybozu.co.jp

cybozu.co.jp

 

QA として入社して1年経った話

はじめまして。2021 年に新卒として入社した大畑と田口と久松です。本記事では 3 人で入社から 1 年の振り返りをしてみました。

自己紹介

大畑
2021 年新卒入社。Garoon QA チームに所属。ラーメンとコーヒーが好き。
田口
PSIRT に所属していて、 kintone を担当しています。 最近福岡に移住しました。中華鍋 2 台持ち。
久松
kintone 開発チームの QA です。カナダからリモートワークしています。

QA:Quality Assurance の略。本記事ではソフトウェアの QA エンジニア。
PSIRT:Product Security Incident Response Team の略。製品セキュリティを専門とするチーム。

入社から1年が経ちましたが…

最近はどんな業務をしてる?

久松:
試験の設計や実施を主にしています。開発手法はスクラムを採用していて、PBI の受け入れ条件を満たしているか確認する受入試験から細かな挙動も確認する機能試験、毎月の新しいバージョンのアップデートが問題なく行えるかの移行試験まで試験は様々です。要件検討時やPG(プログラマー) による実装着手前などの早い段階から開発に関わります。

大畑:
Garoon 開発チームでも開発手法はスクラムを採用しています。QA チームではテストタスクの他にリリースに関わるタスクをやっています。週に1度の予定としては、スプリントレビューや QA チームのふりかえり・Weekly ミーティングがあります。テストの打ち合わせ・設計・実施のタスクは不定期で発生します。QA チームの朝会と、自分が参加している開発系プロジェクトの朝会は毎日やっています。

同期3人の普段のスケジュール例(あさかいやテスト活動など)
普段のスケジュール例

田口:
定常業務としては、プロダクトの脆弱性検証・評価、社内で利用している OSS の構成管理、外部機関による脆弱性監査や検証の依頼・対応、脆弱性報奨金制度の運営・対応、など。他には開発の差分に対して、脆弱性検証が必要かどうかをバックログの内容やソースコードを見ながら判断する検証要件確認、スプリントレビュー/プランニングに参加して開発内容と状況のキャッチアップもしています。

久松:
みんな QA ポジションで入社したけど、扱っているタスクが結構違いますよね。日々の開発に関してだけでなく、改善活動や勉強会の企画など各々のモチベーションにあったことにも挑戦している印象があります。

田口:
今は脆弱性検証を一部自動化しようというプロジェクトやサマーインターン[※1]のメンターになったのでその準備などもやっています。

大畑:
既存のテストを楽にするプロジェクトなど、QA チームの活動をより効率化する改善活動も行っています!

久松:
開発本部に配属されたころから毎週3人でオンラインランチをしていますよね。日常の話だけじゃなくてお互いの業務の話とかもできていて良いなと思っています。セキュリティや品質全般に関してそれぞれ違う視点からディスカッションができます。

配属されたてのころはどうでした?

久松:
開発本部に所属してすぐにエンジニア新人研修が始まりました。私は出身が情報系じゃなくてソフトウェアはほんの少しだけって感じだったので頭に「?」がいっぱいでした。あとで先輩や研修担当の方に相談して、自分の業務だとこの辺まで知っていたら大丈夫、などを教えてもらいました。QA に対しては有志のQA 勉強会支援チーム(ミネルヴァ)が別途 QA 入門講義を開いてくださったので、何もかも不安で仕方ない…!ということはありませんでした。

大畑:
自分もです。特にミネルヴァの QA 入門講義では、ヒアリングをしてもらって私たちに必要そうな講義をしてもらえて、とてもありがたかったです。チームに配属されてからはチームの先輩方が研修用の kintone アプリを用意してくださっていて、取り組むべきことが明確になっていました。必要な情報や手順がまとまっていて、テストツールの使い方から環境構築、製品知識まで幅広く学べました。

田口:
web アプリケーションや脆弱性に対する知識が不足しているなーと感じていたので、学習に専念する期間を 3 ヶ月くらい欲しいです!と先輩方に相談して、快く OK して頂きました。わざと脆弱性を組み込んだ「やられアプリ」とその改修版の開発を最終成果物のテーマとしてやっていました。web アプリケーションや脆弱性の仕組み、その対策を実装しながら同時に学んでいけました。自分的にはその期間が本当にありがたく、その経験が今の業務でもかなり役に立っています。

関わる人やチームの雰囲気はどう?

大畑:
同じ QA チームのメンバーとモブで作業することが多いです。タスクによって PG や PM(プロダクトマネージャー)、TC(テクニカルライター) の方々とも多く関わります。

久松:
自分もPM、TCの方を含めいろんな職能の方との関わりがあります。中でも PG と QA でスクラムチームになっていることから、特にその間でのやりとりが多いです。

田口:
PSIRT は毎日の朝会やざつだんで話す機会があります。プロダクトごとにサブチームが分かれていて、PG/QA とのやりとりも多いです。

久松:
専門知識や普段の業務のことで関わる人もいるし、開発チーム以外にも心理的安全性の意味で関わる人もいます。同期の 3 人はどちらの性質もあるのでよく喋るしありがたいです。

大畑:
同期の 3 人で、触ったことない技術を一緒に学ぶ勉強会をしたり毎週ランチ会をしたりするのが楽しいです。入社して半年後に東京オフィスではじめて 3 人が実際に会うことができましたね。

田口:
これまでリモートだけの関わりだったとは思えないほどスッと馴染みましたね。

たいへんなことあった?

大畑:
オンライン入社だったこともあり、最初は kintone 上でテキストで先輩に質問するときに緊張していました。柔軟にビデオミーティングで教えていただいたり 1on1 をしていただいているおかげで、今はとても心理的に安全なテキストでのやりとりができるようになりました。

田口:
僕も同じ感じです。基本的にテキストコミュニケーションがほとんどですが、チームの雰囲気はとてもあたたかく、壁を感じないです。チーム外の直接話したことがない人でも、kintone 上でざつだんをしていたりします。ときどき自分の分報で料理の話題で盛り上がりますね。

久松:
私の業務では普段 kintone 上でのコミュニケーションがメインなので、職能やプロダクトで壁や距離感を感じることはあまりないかなと思います。一方で、テキストなので言い回しに気を使うことが多いかなと思います。

zoom上で同期3人でモブをしている様子
ブログをモブで作っている様子

久松:
配属されたての研修時や、慣れないタスクについて聞きたい時、コミュニケーションの仕方が難しいと思う時があったかもしれません。特に私はカナダからリモートで働くのが珍しい例だったので、いろいろな立場の方との粘り強いコミュニケーションが必要でした。概して変化が多いので様々なやりとりが発生しますが、理不尽だったり建設的でなかったりしたものはあんまり思い当たらないです。

田口:
変化が多いのは同感です。最初は情報の海に溺れました。kintone 上にはリアルタイムに大量の情報が飛び交ってるし、とても流れがはやいです。今ではそれにも慣れましたが、最初は大変でした。

大畑:
自分はまだまだ完全には慣れていないけれど、大量の情報を楽しめるようになりました。

入社してどうだった?

田口:
PSIRT 内でやっていきたいことを中心に進められていて、やりがいも感じています。研修もそうですが、チームには本人のやりたいことを尊重する体制があって、実際に挑戦ができていることはすごいなと思いました。働き方や働く場所もチームやマネージャーにも快く認めて頂いて、自由に働けています。個人的に今の環境はすごく恵まれていると感じていて満足しており、入社して良かったと思っています。

久松:
田口さんは金曜だけ午前あがりにして、他の曜日にちょっとずつ多めに働くっていうのやっていますよね。働いてるとタスクに関してだけじゃなくて、多かれ少なかれ個人の生活に関する会話もでてくるなと感じます。今日お腹痛いですとか。その上、私のチームはリモートの方が多いのでテキストコミュニケーションが基本です。ですがタスクでも個人の話でも会話では HRT(謙虚/尊敬/信頼)を大事にと思っている方が多くて良いなと感じます。

大畑:
HRT を大事にされている方が多いこと、とても同感です。チーム内のモブや PG さんとのミーティングなど色々な場面で HRT を感じます。家で一人で仕事をしていると色々不安なこともありましたが、先輩や PG さんが zoom で優しく教えてくれますし、日常会話もできるつながりがあるので楽しく仕事できています。タスクの幅が広いこともあり、日々新しいことを学んだり実践できるのが楽しいです。

まとめ

  • エンジニア研修やチームでの研修、QA 勉強会支援チーム(ミネルヴァ)の勉強会が充実していて安心して業務に入ることができた
  • オンラインでも壁を感じることなく業務ができている
  • 同じ QA 職でも所属チームでそれぞれ特色がある

おつかれさまでした。2年目も頑張っていきましょう!

関連リンク:

[※1]2022 サマーインターンについてはこちら!

 

kintoneのアクセシビリティ改善とESLintルールの整備

kintoneのアクセシビリティ改善とESLintルールの整備

こんにちは。Poca11y(ポカリ)チームのSUGI(@blindsoup2p1)と小林(@sukoyakarizumu)です。

わたしたちPoca11yチームは「kintone」のアクセシビリティ改善活動に参加しています。この記事ではkintoneのアクセシビリティを改善するチーム体制について解説します。さらにPoca11yチームとkintone開発チームが協力して整備したアクセシビリティを強化するためのESLintルールについても解説します。

Poca11y(アクセシビリティ)チームとkintoneのアクセシビリティ改善

Poca11yチームとは

Poca11yチームはサイボウズ全体の「アクセシビリティ」向上を目的としたチームです。Poca11yチームでは主に以下3種類の活動を行なっています。

  • 社内啓発:アクセシビリティの社内研修・勉強会・ガイドライン作成などを行います。
  • 製品改善:サイボウズ製品のアクセシビリティを改善する実装や評価を行います。
  • 社外発信:社内啓発や製品改善の取り組みを発表や記事等で社外に公開します。

このうち製品改善では、kintone・Garoon・サイボウズ Officeといったそれぞれの製品開発チームメンバーと一緒にアクセシビリティの改善を行なっています。現在は主にkintone開発チームのアクセシビリティ改善に参画しています。

kintoneのユーザー体験を最高にするチーム──「Mantleチーム」

kintone開発チームにはサブチームのひとつとして、kintoneのユーザー体験を最高にするチーム──通称「Mantleチーム」があります。Mantleチームの目標は、kintoneのコンポーネントライブラリやコンポーネントドキュメントを整備し、kintone全体で一貫したユーザー体験を提供することです。よりよいユーザー体験を提供するためには様々な専門領域の知見が必要です。このため、Mantleチームにはデザイン・フロントエンド・アプリケーション品質などの専門領域を持ったメンバーが集まっており、それぞれの専門分野を生かしながら活動しています。Mantleチームについて詳細を知りたい方は以下の記事をご覧ください。

blog.cybozu.io

Poca11yチームとMantleチームの関わり

Poca11yチームはアクセシビリティを専門領域に持つメンバーとしてMantleチームに参加しています。Poca11yチームでは特にコンポーネントライブラリのアクセシビリティ強化につとめています。たとえば以下のような活動を行なっています。

  • 共通コンポーネントのHTMLやWAI-ARIAを検討してフロントエンドエンジニアにフィードバックする。
  • フォントやカラーなどのビジュアルデザインをアクセシビリティの観点からレビューする。
  • アクセシビリティの自動チェックツールを整備する。

さらに、アクセシビリティ以外のタスクについても積極的に参画し、他の専門分野を持つメンバーと横断的に活動しています。たとえば以下のような活動を行なっています。

  • フロントエンドエンジニアと一緒に、他のサブチームが開発したコンポーネントをライブラリに集約する。
  • デザイナーと一緒に、コンポーネントドキュメントを執筆する。
  • 品質保証のメンバーと一緒に、テストを設計し自動テストを実装する。

さまざまな専門領域を横断してお互いにスキルを高め合っていけることがMantleチームに参加する醍醐味です。

アクセシビリティを強化するESLintルールを整備する

Poca11yチームでは、Mantleチームが結成される前からkintone開発チームと協力してさまざまなアクセシビリティ改善活動を行なっています。そのひとつがアクセシビリティを強化するためのESLintルールの整備です。

ESLintにはeslint-plugin-jsx-a11yというプラグインがあります。eslint-plugin-jsx-a11yはJSXファイルでアクセシビリティの問題を特定する静的チェッカーで、30以上のルールから構成されています。

kintoneはESLintを利用しているため、eslint-plugin-jsx-a11yの導入によってアクセシビリティを向上できると考えました。また、ルールが学習されることでエンジニアのアクセシビリティスキルの向上もはかれると考えました。

ESLintルールを精査する

kintoneにeslint-plugin-jsx-a11yを導入する際はkintone開発チームと一緒にルールを精査した上で、ひとつひとつのルールについて適用するかどうかを検討することにしました。

まずeslint-plugin-jsx-a11yに含まれているすべてのルールの意味を精査しました。Poca11yチームのメンバーを中心に、ルールの意味や効果をスプレッドシートにまとめていきました。

スクリーンショット:ルールの意味をまとめたスプレッドシート。

スプレッドシートを作成したのち、ESLintルールを整備する関係者を集め、それぞれのルールの意味を確認して適用するかどうかを決めていきました。具体的には週1回のペースでkintone開発チーム・フロントエンドエキスパートチーム・Poca11yチームのメンバーが集まる会議体を設定しました。この時間でスプレッドシートを閲覧しながらひとつひとつのルールを確認し、ルールの適用/不適用をまとめた設定ファイルを作成することにしました。また同時に議事録もとり、kintone開発チームのコミュニケーションスペースで共有しました。

スクリーンショット:ルールを議論した結果をまとめた議事録。

議論になったルール

ここでは具体的に議論したいくつかのルールについて、ルールの意味・議論の内容・ルールの適用結果を紹介します。

anchor-is-valid

anchor-is-validは、a要素に対して適切なhref属性値がついているか検証するルールです。たとえばhref="javascript:void(0)"href="#"などが不適切な値とみなされます。

kintoneではルールを有効化しました。残念ながら現状のkintoneではこのルールに違反している箇所が多くあります。特に開発された時期が古いコンポーネントではhref属性値に不適切な値を設定してa要素でボタンを表現している例が散見されます。今後徐々にルールの違反を減らしていきたいと考えています。

no-redundant-role

no-redundant-roleは、HTML要素に対して暗黙的なロールをつけることを制限するルールです。たとえば、button要素は暗黙的なロールとしてbuttonロールを持つため、button要素に対してrole="button"をつけることを制限します。

議論した結果、kintoneではこのルールを無効化しました。kintoneではあえて明示的に暗黙的なロールを指定することがあるためです。冗長なロールを指定することは、たとえば以下のような場合に有効です。

  • Safariは、リストスタイルが消されたul要素・ol要素のlistロールを無視してしまいます*1。このため、ul要素を使ってもスクリーンリーダーは「リスト」であることを読み上げません。現象を回避するには、ul要素・ol要素に対してrole="list"を明示的に指定する必要があります。
  • 古いバージョンのSafariは、img要素のsrc属性にsvgファイルを指定した場合、imgロールを無視してしまいます*2。このため、スクリーンリーダーは「画像」であることや、alt属性で指定された代替テキストを読み上げません。現象を回避するには、img要素に対してrole="img"を明示的に指定する必要があります。
  • 古いブラウザやスクリーンリーダーは、main要素・header要素・footer要素・nav要素などのランドマークロールを無視してしまう場合があります。このため、main要素を使っても「メイン」であることを読み上げないことがあります。現象を回避するには、ランドマークロールを明示的に指定する必要があります。たとえば、main要素に対してrole="main"を指定します。

no-noninteractive-tabindex

no-noninteractive-tabindexは、tabindex属性を付与できるロールをインタラクティブロールのみに制限するルールです。インタラクティブロールにはbuttonロール、linkロール、checkboxロール、menuitemロールなどのロールが該当します。インタラクティブロール以外に、tabpanelロールは例外とすることが推奨されています。

議論した結果、kintoneではtabpanelロールとdialogロールを例外に加えて、ルールを有効化しました。dialogロールを例外とした理由は、kintoneのモーダルダイアログがダイアログ自体にフォーカスするためです。

kintoneのモーダルダイアログは、本来のモーダルダイアログとフォーカスの挙動が異なります。本来、モーダルダイアログは、ダイアログが開いたときダイアログの内部の要素にフォーカスします。ダイアログ自体にはフォーカスしません。dialog要素の仕様ではdialog要素にtabindex属性を指定してはならないとされています*3。しかし、kintoneのモーダルダイアログは、ダイアログを開いたときダイアログ自体にフォーカスします。kintoneのモーダルダイアログの挙動がdialog要素の仕様と異なる理由は、dialog要素の仕様が定義される前に実装されたコンポーネントライブラリを利用しているためです。このコンポーネントライブラリのモーダルダイアログは、ダイアログ自体にフォーカスする実装となっています。

kintoneのモーダルダイアログの実装はdialog要素の仕様にはそぐわないものの、多くの支援技術で問題なく操作できることがわかっています。このため現状はダイアログ全体にフォーカスする実装を許容することにしました。

完成したESLintルールと今後の課題

kintone開発チームでは定義したルールに基づいてeslint-a11y-jsx-pluginを利用しています。日々ルールがチェックされることで、マークアップの問題を未然に防ぐことができます。また開発者がルールを学ぶことで、アクセシビリティのスキルを向上できると考えています。

また、このルールは社外の開発者が利用することも想定しています。定義したルールはサイボウズが外部公開しているeslint-configに導入されています。このeslint-configはkintoneをカスタマイズするプログラムや連携サービスで利用されています。特にkintoneはサイボウズ外の開発者によってカスタマイズされることが想定された製品です。カスタマイズも含めて統一的にアクセシビリティの品質を確保するため、eslint-configを公開することは有用だと考えています。

サイボウズが外部公開しているeslint-configへマージしたプルリクエストは以下です。変更したルールを確認できます。

github.com

github.com

今後、ルールを追加・変更することも検討しています。ルールを精査したときにはさまざまな事情で無効化したルールの中には、現在は有効化できるルールもあります。これからも段階的にルールを再検討していこうと考えています。

kintoneのアクセシビリティやユーザー体験を高めてくれるメンバーを募集しています

kintoneのアクセシビリティにはまだまだ改善の余地があります。ESLintのような自動チェックツールの強化は改善の第一歩です。ほかにも以下に示すような様々な課題へ取り組む必要があります。

  • より多くのコンポーネントのアクセシビリティ強化
  • アクセシビリティに関する問題の定量的な計測
  • アクセシビリティガイドラインの整備・啓発
  • 多様なユーザーへのリサーチ

また、アクセシビリティだけでなくほかの分野を横断しながら、ユーザー体験全体を高める必要もあります。

kintone開発チームでは、アクセシビリティやユーザー体験を高めてくれるメンバーを募集しています。以下の募集要項からご応募ください。

  • Meety

meety.net

  • フロントエンド募集

cybozu.co.jp

  • デザイナー募集

cybozu.co.jp

cybozu.co.jp

cybozu.co.jp

 

エンジニアインターンシップ2022を開催します!

こんにちは!Garoon開発 兼 エンジニアインターン運営の羽田です。

サイボウズでは毎年夏に、エンジニア/デザイナー向けサマーインターンシップを開催しています。今年も昨年に引き続き、フルリモートでインターンを開催します。

インターン2022サイトロゴ

製品開発を行うチームに加えて、昨年から引き続き製品開発を支えるチームのコースを幅広くご用意しています。 課題や業務を通して、チームが実際に使っている環境を体験しながら、開発や現場の雰囲気に触れることができます。 社長とのランチ会や社内イベント、気になる社員を指名して1対1で話す時間など、コンテンツ以外の社員との交流も予定しています。

サイボウズの風土や雰囲気をインターンを通して感じてみませんか?皆様からのエントリーをお待ちしております!

対象

  • 2024年4月または10月に入社が可能な方
  • エントリー時に在学中または卒業後1年未満の方 (学歴不問)
  • 就業経験*1が1年未満の方
  • 日本国内でインターンに参加できる方 (コースによってこの条件の有無が異なるので、詳細は特設サイトをご確認ください)

エントリー開始日

2022年4月25日(月)より随時エントリー受付開始

開催コース

  • Webサービス開発(kintone)
  • モバイルアプリ開発
  • Kubernetes基盤開発
  • ストレージ new!
  • 品質保証
  • 生産性向上
  • プロダクトセキュリティ
  • フロントエンドエキスパート
  • デザイン&リサーチ

各コースの内容、応募方法や報酬などの詳細は特設サイトをご確認ください。 cybozu.co.jp

※コースによって開催時期や応募期間が異なりますのでご注意ください。

参考情報

昨年までのインターンの報告も投稿しておりますので、ぜひご覧ください。 blog.cybozu.io

*1:就業経験とは、原則として正社員や契約社員などでの 勤務経験を指します。学業と並行して行ったアルバイトや インターンシップは含まれません。