From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../client-side_javascript_frameworks/index.html | 138 +++++ .../react_components/index.html | 450 ++++++++++++++ .../react_getting_started/index.html | 468 ++++++++++++++ .../react_todo_list_beginning/index.html | 599 ++++++++++++++++++ .../vue_getting_started/index.html | 301 +++++++++ .../cross_browser_testing/accessibility/index.html | 624 +++++++++++++++++++ .../automated_testing/index.html | 620 +++++++++++++++++++ .../feature_detection/index.html | 357 +++++++++++ .../cross_browser_testing/html_and_css/index.html | 508 +++++++++++++++ .../cross_browser_testing/index.html | 47 ++ .../cross_browser_testing/introduction/index.html | 209 +++++++ .../cross_browser_testing/javascript/index.html | 521 ++++++++++++++++ .../testing_strategies/index.html | 372 +++++++++++ .../your_own_automation_environment/index.html | 688 +++++++++++++++++++++ files/ja/learn/tools_and_testing/index.html | 49 ++ 15 files changed, 5951 insertions(+) create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html create mode 100644 files/ja/learn/tools_and_testing/index.html (limited to 'files/ja/learn/tools_and_testing') diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html new file mode 100644 index 0000000000..f49b505c56 --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html @@ -0,0 +1,138 @@ +--- +title: Understanding client-side JavaScript frameworks +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks +tags: + - Beginner + - Frameworks + - JavaScript + - Learn + - NeedsTranslation + - TopicStub + - client-side +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks +--- +
{{LearnSidebar}}
+ +

JavaScriptフレームワークは、最新のフロントエンドWeb開発に欠かせないものであり、開発者にスケーラブルでインタラクティブなWebアプリケーションを構築するための試行錯誤されたツールを提供しています。現代の多くの企業では、フレームワークをツールの標準的な一部として使用しているため、多くのフロントエンド開発の仕事でフレームワークの経験が必要とされています。

+ +

フロントエンド開発者を目指していると、フレームワークを学ぶ際にどこから始めればいいのか悩むことがあります。— there are so many different frameworks to choose from, new ones appear all the time, they mostly work in a similar way but do some things differently, and there are some specific things to be careful about when using frameworks.

+ +

この記事では、あなたがフレームワークを学び始めるための快適な出発点を提供することを目的としています。私たちは、React/ReactDOMやVue、その他の特定のフレームワークについて知っておく必要があるすべてのことを網羅的に教えることを目指しているわけではありません。その代わりに、以下のようなより基本的な質問に答えたいと思います。

+ + + +

その後、異なるフレームワークの選択の要点をカバーするチュートリアルをいくつか提供し、あなたが自分自身でより深く学び始めるのに十分なコンテキストと親しみやすさを提供します。アクセシビリティなどのウェブプラットフォームの基本的なベストプラクティスを忘れずに、実用的な方法でフレームワークについて学んでいただきたいと思います。

+ +

Get started now, with "Introduction to client-side frameworks"

+ +

Prerequisites

+ +

You should really learn the basics of the core web languages first before attempting to move on to learning client-side frameworks — HTML, CSS, and especially JavaScript.

+ +

Your code will be richer and more professional as a result, and you'll be able to troubleshoot problems with more confidence if you understand the fundamental web platform features that the frameworks are building on top of.

+ +

Introductory guides

+ +
+
1. Introduction to client-side frameworks
+
We begin our look at frameworks with a general overview of the area, looking at a brief history of JavaScript and frameworks, why frameworks exist and what they give us, how to start thinking about choosing a framework to learn, and what alternatives there are to client-side frameworks.
+
2. Framework main features
+
Each major JavaScript framework has a different approach to updating the DOM, handling browser events, and providing an enjoyable developer experience. This article will explore the main features of “the big 4” frameworks, looking at how frameworks tend to work from a high level and the differences between them.
+
+ +

React tutorials

+ +
+

Note: React tutorials last tested in May 2020, with React/ReactDOM 16.13.1 and create-react-app 3.4.1.

+ +

If you need to check your code against our version, you can find a finished version of the sample React app code in our todo-react repository. For a running live version, see https://mdn.github.io/todo-react-build/.

+
+ +
+
1. Getting started with React
+
In this article we will say hello to React. We'll discover a little bit of detail about its background and use cases, set up a basic React toolchain on our local computer, and create and play with a simple starter app, learning a bit about how React works in the process.
+
2. Beginning our React todo list
+
Let's say that we’ve been tasked with creating a proof-of-concept in React – an app that allows users to add, edit, and delete tasks they want to work on, and also mark tasks as complete without deleting them. This article will walk you through putting the basic App component structure and styling in place, ready for individual component definition and interactivity, which we'll add later.
+
3. Componentizing our React app
+
At this point, our app is a monolith. Before we can make it do things, we need to break it apart into manageable, descriptive components. React doesn’t have any hard rules for what is and isn’t a component – that’s up to you! In this article, we will show you a sensible way to break our app up into components.
+
4. React interactivity: Events and state
+
With our component plan worked out, it's now time to start updating our app from a completely static UI to one that actually allows us to interact and change things. In this article we'll do this, digging into events and state along the way.
+
5. React interactivity: Editing, filtering, conditional rendering
+
As we near the end of our React journey (for now at least), we'll add the finishing touches to the main areas of functionality in our Todo list app. This includes allowing you to edit existing tasks and filtering the list of tasks between all, completed, and incomplete tasks. We'll look at conditional UI rendering along the way.
+
6. Accessibility in React
+
In our final tutorial article, we'll focus on (pun intended) accessibility, including focus management in React, which can improve usability and reduce confusion for both keyboard-only and screen reader users.
+
7. React resources
+
Our final article provides you with a list of React resources that you can use to go further in your learning.
+
+ +

Ember tutorials

+ +
+

Note: Ember tutorials last tested in May 2020, with Ember/Ember CLI version 3.18.0.

+ +

If you need to check your code against our version, you can find a finished version of the sample Ember app code in the ember-todomvc-tutorial repository. For a running live version, see https://nullvoxpopuli.github.io/ember-todomvc-tutorial/ (this also includes a few additional features not covered in the tutorial).

+
+ +
+
1. Getting started with Ember
+
In our first Ember article we will look at how Ember works and what it's useful for, install the Ember toolchain locally, create a sample app, and then do some initial setup to get it ready for development.
+
2. Ember app structure and componentization
+
In this article we'll get right on with planning out the structure of our TodoMVC Ember app, adding in the HTML for it, and then breaking that HTML structure into components.
+
3. Ember interactivity: Events, classes and state
+
At this point we'll start adding some interactivity to our app, providing the ability to add and display new todo items. Along the way, we'll look at using events in Ember, creating component classes to contain JavaScript code to control interactive features, and setting up a service to keep track of the data state of our app.
+
4. Ember Interactivity: Footer functionality, conditional rendering
+
Now it's time to start tackling the footer functionality in our app. Here we'll get the todo counter to update to show the correct number of todos still to complete, and correctly apply styling to completed todos (i.e. where the checkbox has been checked). We'll also wire up our "Clear completed" button. Along the way, we'll learn about using conditional rendering in our templates.
+
5. Routing in Ember
+
In this article we learn about routing or URL-based filtering as it is sometimes referred to. We'll use it to provide a unique URL for each of the three todo views — "All", "Active", and "Completed".
+
6. Ember resources and troubleshooting
+
Our final Ember article provides you with a list of resources that you can use to go further in your learning, plus some useful troubleshooting and other information.
+
+ +

Vue tutorials

+ +
+

Note: Vue tutorials last tested in May 2020, with Vue 2.6.11.

+ +

If you need to check your code against our version, you can find a finished version of the sample Vue app code in our todo-vue repository. For a running live version, see https://mdn.github.io/todo-vue/dist/.

+
+ +
+
1. Getting started with Vue
+
Now let's introduce Vue, the third of our frameworks. In this article, we'll look at a little bit of Vue background, learn how to install it and create a new project, study the high-level structure of the whole project and an individual component, see how to run the project locally, and get it prepared to start building our example.
+
2. Creating our first Vue component
+
Now it's time to dive deeper into Vue, and create our own custom component — we'll start by creating a component to represent each item in the todo list. Along the way, we'll learn about a few important concepts such as calling components inside other components, passing data to them via props and saving data state.
+
3. Rendering a list of Vue components
+
At this point we've got a fully working component; we're now ready to add multiple ToDoItem components to our App. In this article we'll look at adding a set of todo item data to our App.vue component, which we'll then loop through and display inside ToDoItem components using the v-for directive.
+
4. Adding a new todo form: Vue events, methods, and models
+
We now have sample data in place and a loop that takes each bit of data and renders it inside a ToDoItem in our app. What we really need next is the ability to allow our users to enter their own todo items into the app, and for that, we'll need a text <input>, an event to fire when the data is submitted, a method to fire upon submission to add the data and rerender the list, and a model to control the data. This is what we'll cover in this article.
+
5. Styling Vue components with CSS
+
The time has finally come to make our app look a bit nicer. In this article, we'll explore the different ways of styling Vue components with CSS.
+
6. Using Vue computed properties
+
In this article we'll add a counter that displays the number of completed todo items, using a feature of Vue called computed properties. These work similarly to methods but only re-run when one of their dependencies changes.
+
7. Vue conditional rendering: editing existing todos
+
Now it is time to add one of the major parts of functionality that we're still missing — the ability to edit existing todo items. To do this, we will take advantage of Vue's conditional rendering capabilities — namely v-if and v-else — to allow us to toggle between the existing todo item view and an edit view where you can update todo item labels. We'll also look at adding functionality to delete todo items.
+
8. Focus management with Vue refs
+
We are nearly done with Vue. The last bit of functionality to look at is focus management, or put another way, how we can improve our app's keyboard accessibility. We'll look at using Vue refs to handle this — an advanced feature that allows you to have direct access to the underlying DOM nodes below the virtual DOM, or direct access from one component to the internal DOM structure of a child component.
+
9. Vue resources
+
Now we'll round off our study of Vue by giving you a list of resources that you can use to go further in your learning, plus some other useful tips.
+
+ +

Which frameworks did we choose?

+ +

We are publishing our initial set of articles with guides focusing on three of the major frameworks out there — React/ReactDOM, Ember, and Vue. There is a variety of reasons for this:

+ + + +

We want to say this upfront — we've not chosen the frameworks we are focusing on because we think they are the best, or because we endorse them in any way. We just think they score highly on the above criteria.

+ +

Note that we were hoping to have more frameworks included upon initial publication, but we decided to release the content and then add more framework guides later, rather than delay it longer. If your favourite framework is not represented in this content and you'd like to help change that, feel free to discuss it with us! Get in touch with us via Matrix, or Discourse, or drop us a mail on the mdn-admins list.

diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html new file mode 100644 index 0000000000..43eedc76eb --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html @@ -0,0 +1,450 @@ +--- +title: React アプリのコンポーネント化 +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}
+ +

この時点では、アプリは一枚岩です。アプリに何かをさせる前に、管理しやすく、記述しやすいコンポーネントに分解する必要があります。React には、何がコンポーネントで何がコンポーネントでないかという難しいルールはありません。それはあなた次第なのです!この記事では、アプリをコンポーネントに分解するための賢明な方法を紹介します。

+ + + + + + + + + + + + +
前提条件: +

HTMLCSSJavaScript のコア言語に精通していること、ターミナル/コマンドラインの知識があること。

+
目的:Todo リストアプリをコンポーネントに分割するための賢明な方法を示すこと。
+ +

最初のコンポーネントの定義

+ +

コンポーネントの定義は、ある程度練習をするまでは難しいと思われるかもしれませんが、要点は以下の通りです。

+ + + +

2 番目の箇条書きは特に価値があります: 一般的な UI 要素からコンポーネントを作成することで、コードを一箇所で変更することができ、そのコンポーネントが使用される場所のどこでも変更内容を確認することができます。また、すぐにすべてをコンポーネントに分割する必要もありません。2 つ目の箇条書きをヒントに、UI の中で最も再利用され、最も重要な部分である TODO リスト項目からコンポーネントを作成してみましょう。

+ +

<Todo />の作成

+ +

コンポーネントを作る前に、そのための新しいファイルを作らなければなりません。実は、コンポーネント用の新しいディレクトリの作成が必要です。次のコマンドは、components ディレクトリを作成し、その中に Todo.js というファイルを作成します。これらを実行する前に、アプリのルートにいることを確認してください!

+ +
mkdir src/components
+touch src/components/Todo.js
+ +

新しい Todo.js ファイルは今は空です。ファイルを開いて最初の行に次を入力してください。

+ +
import React from "react";
+ +

今回は Todo というコンポーネントを作る予定なので、以下のように Todo.js にもそのためのコードを追加していきます。このコードでは、関数の定義とエクスポートを一行で定義しています。

+ +
export default function Todo() {
+  return (
+
+  );
+}
+ +

ここまでは問題ありませんが、このコンポーネントは何かを返さなければなりません!src/App.js に戻って、最初の <li> をコピーし、Todo.js に貼り付けて、以下のように読み込みます。

+ +
export default function Todo() {
+  return (
+    <li className="todo stack-small">
+      <div className="c-cb">
+        <input id="todo-0" type="checkbox" defaultChecked={true} />
+        <label className="todo-label" htmlFor="todo-0">
+          Eat
+        </label>
+      </div>
+      <div className="btn-group">
+        <button type="button" className="btn">
+          Edit <span className="visually-hidden">Eat</span>
+        </button>
+        <button type="button" className="btn btn__danger">
+          Delete <span className="visually-hidden">Eat</span>
+        </button>
+      </div>
+    </li>
+  );
+}
+ +
+

注意: コンポーネントは常に何かを返さなければなりません。もし今後あなたが何も返さないコンポーネントをレンダリングしようとしたら、React はブラウザにエラーを表示するでしょう。

+
+ +

これで Todo コンポーネントは完成しました。App.js で、ファイルの先頭付近に次の行を追加して Todo をインポートします。

+ +
import Todo from "./components/Todo";
+ +

このコンポーネントをインポートすると、App.js<li> 要素をすべて <Todo /> コンポーネント呼び出しに置き換えることができます。<ul> は以下のようになるはずです。

+ +
<ul
+  role="list"
+  className="todo-list stack-large stack-exception"
+  aria-labelledby="list-heading"
+>
+  <Todo />
+  <Todo />
+  <Todo />
+</ul>
+ +

ブラウザに戻ってみると、何か不幸なことに気づくでしょう: あなたのリストは、最初のタスクを3回繰り返すようになりました!

+ +

Our todo list app, with todo components repeating because the label is hardcoded into the component

+ +

私たちは食べたいだけではなく、他にもやるべきこと — そう、TODO があります。次に、異なるコンポーネント呼び出しで別々のコンテンツをレンダリングする方法を見てみましょう。

+ +

「一意の」 <Todo /> を作成

+ +

コンポーネントが強力なのは、UI の一部を再利用し、その UI のソースを 1 か所で参照できるからです。問題は、通常、各コンポーネントのすべてを再利用するのではなく、ほとんどの部分を再利用しつつ小さな部分を変更したいということです。そこでプロップ( props )の出番です。

+ +

name に何が入るでしょう?

+ +

完了させたいタスクの名前を追跡するために、それぞれの <Todo /> コンポーネントが一意の名前を表示するようにしなければなりません。

+ +

App.jsでは、それぞれの <Todo /> に名前のプロップを与えます。先ほどのタスクの名前を使ってみましょう。

+ +
<Todo name="Eat" />
+<Todo name="Sleep" />
+<Todo name="Repeat" />
+ +

ブラウザを更新すると...以前と全く同じものが表示されます。<Todo /> にプロップを与えましたが、まだ使っていません。Todo.js に戻って解決しましょう。

+ +

最初に Todo() 関数の定義を変更して、props をパラメータとして受け取るようにします。props がコンポーネントによって正しく受信されているかどうかを確認したい場合は、先ほどと同様に console.log()props を取得することができます。

+ +

コンポーネントが props を取得していることを確認したら、Eatname のプロップで置き換えることができます。覚えておいてください: JSX の式の途中では、中括弧を使って変数の値を注入します。

+ +

これらをまとめると、Todo() 関数は次のようになるはずです。

+ +
export default function Todo(props) {
+  return (
+    <li className="todo stack-small">
+      <div className="c-cb">
+        <input id="todo-0" type="checkbox" defaultChecked={true} />
+        <label className="todo-label" htmlFor="todo-0">
+          {props.name}
+        </label>
+      </div>
+      <div className="btn-group">
+        <button type="button" className="btn">
+          Edit <span className="visually-hidden">{props.name}</span>
+        </button>
+        <button type="button" className="btn btn__danger">
+          Delete <span className="visually-hidden">{props.name}</span>
+        </button>
+      </div>
+    </li>
+  );
+}
+ +

これで、ブラウザには3つの一意のタスクが表示されるようになりました。しかし、もう一つの問題が残っています: これらはすべてデフォルトでチェックされています。

+ +

Our todo list, with different todo labels now they are passed into the components as props

+ +

それは completed ですか?

+ +

元の静的リストでは、Eat だけがチェックされていました。もう一度言いますが、<Todo />コンポーネントを構成するUIのほとんどを再利用しつつ、一つだけ変更したいのです。これは別のプロップが良い仕事をしてくれます!App.js での各 <Todo /> の呼び出しには、完了したことを示す新しいプロップを与えます。最初の (Eat) は true の値を持ち、残りは false にします。

+ +
<Todo name="Eat" completed={true} />
+<Todo name="Sleep" completed={false} />
+<Todo name="Repeat" completed={false} />
+ +

先ほどと同様に、これらのプロップを実際に使用するためには Todo.js に戻る必要があります。<input />defaultChecked 属性の値が completed したプロップと同じになるように変更します。これで、Todo コンポーネントの <input /> 要素は次のようになります。

+ +
<input id="todo-0" type="checkbox" defaultChecked={props.completed} />
+ +

そして、ブラウザを更新すると、Eat だけがチェックされていることが表示されるようになるはずです。

+ +

Our todo list app, now with differing checked states - some checkboxes are checked, others not

+ +

<Todo /> コンポーネントのconpleted プロップを変更すると、ブラウザはそれに応じてレンダリングされた同等のチェックボックスをチェックしたり、チェックを外したりします。

+ +

id をください

+ +

現在、<Todo /> コンポーネントはすべてのタスクに todo-0 という id 属性を与えています。これは悪い HTML です、なぜなら id 属性は一意でなければならないからです (CSS や JavaScript などでドキュメントフラグメントの一意な識別子として使用されます)。つまり、各 Todo に対して一意の値を取る id プロップをコンポーネントに与えるべきです。

+ +

最初と同じパターンに従うために、<Todo /> コンポーネントの各インスタンスに todo-i の形式で ID を与えてみましょう。i は毎回1つずつ大きくなっていきます。

+ +
<Todo name="Eat" completed={true} id="todo-0" />
+<Todo name="Sleep" completed={false} id="todo-1" />
+<Todo name="Repeat" completed={false} id="todo-2" />
+ +

ここで Todo.js に戻り、id プロップを使うようにします。これは <input /> 要素の id 属性の値とラベルの htmlFor 属性の値を置き換える必要があります。

+ +
<div className="c-cb">
+  <input id={props.id} type="checkbox" defaultChecked={props.completed} />
+  <label className="todo-label" htmlFor={props.id}>
+    {props.name}
+  </label>
+</div>
+ +

ここまでは順調ですか?

+ +

今のところ React をうまく使っていますが、もっとうまくできるかもしれません!今のコードは反復的です。<Todo /> コンポーネントをレンダリングする3つの行はほぼ同じですが、1つだけ違う点があります: それぞれのプロップの値です。

+ +

JavaScript のコアな能力の一つであるイテレーション(反復処理)を使えば、コードをクリーンアップすることができます。イテレーションを使うためには、まず自分のタスクを再考する必要があります。

+ +

データとしてのタスク

+ +

それぞれのタスクには現在、3つの情報が含まれています: 名前、チェック済みかどうか、そして一意なIDです。このデータはうまくオブジェクトに変換されます。複数のタスクがあるので、このデータを表現するにはオブジェクトの配列が有効です。

+ +

import の後 ReactDOM.render() より前の行で以下の const を作成してください。

+ +
const DATA = [
+  { id: "todo-0", name: "Eat", completed: true },
+  { id: "todo-1", name: "Sleep", completed: false },
+  { id: "todo-2", name: "Repeat", completed: false }
+];
+ +

次に、tasks という名前のプロップとして <App />DATA を渡します。src/index.js の最終行は以下のようになるはずです。

+ +
ReactDOM.render(<App tasks={DATA} />, document.getElementById("root"));
+ +

この配列は、App コンポーネントで props.tasks として利用できるようになりました。よかったら console.log() で確認してください。

+ +
+

注意: ALL_CAPS 定数名は JavaScript では特別な意味はありません; 他の開発者に「このデータはここで定義された後は変更されません」と伝えるための慣習です。

+
+ +

イテレーションによるレンダリング

+ +

オブジェクトの配列をレンダリングするには、それぞれのオブジェクトを <Todo /> コンポーネントに変換しなければなりません。JavaScript では、データを別のものに変換するための配列メソッド Array.prototype.map() を提供しています。

+ +

Above the return statement of App(), make a new const called taskList and use map() to transform it. Let's start by turning our tasks array into something simple: the name of each task:

+ +
const taskList = props.tasks.map(task => task.name);
+ +

Let’s try replacing all the children of the <ul> with taskList:

+ +
<ul
+  role="list"
+  className="todo-list stack-large stack-exception"
+  aria-labelledby="list-heading"
+>
+  {taskList}
+</ul>
+ +

This gets us some of the way towards showing all the components again, but we’ve got more work to do: the browser currently renders each task's name as unstructured text. We’re missing our HTML structure — the <li> and its checkboxes and buttons!

+ +

Our todo list app with the todo item labels just shown bunched up on one line

+ +

To fix this, we need to return a <Todo /> component from our map() function — remember that JSX allows us to mix up JavaScript and markup structures! Let's try the following instead of what we have already:

+ +
 const taskList = props.tasks.map(task => <Todo />);
+ +

Look again at your app; now our tasks look more like they used to, but they’re missing the names of the tasks themselves.  Remember that each task we map over has the id, name, and checked properties we want to pass into our <Todo /> component. If we put that knowledge together, we get code like this:

+ +
const taskList = props.tasks.map(task => (
+  <Todo id={task.id} name={task.name} completed={task.completed} />
+));
+ +

Now the app looks like it did before, and our code is less repetitive.

+ +

Unique keys

+ +

Now that React is rendering our tasks out of an array, it has to keep track of which one is which in order to render them properly. React tries to do its own guesswork to keep track of things, but we can help it out by passing a key prop to our <Todo /> components. key is a special prop that's managed by React – you cannot use the word key for any other purpose.

+ +

Because keys should be unique, we're going to re-use the id of each task object as its key. Update your taskList constant like so:

+ +
const taskList = props.tasks.map(task => (
+    <Todo
+      id={task.id}
+      name={task.name}
+      completed={task.completed}
+      key={task.id}
+    />
+  )
+);
+ +

You should always pass a unique key to anything you render with iteration. Nothing obvious will change in your browser, but if you do not use unique keys, React will log warnings to your console and your app may behave strangely!

+ +

Componentizing the rest of the app

+ +

Now that we've got our most important component sorted out, we can turn the rest of our app into components. Remembering that components are either obvious pieces of UI, or reused pieces of UI, or both, we can make two more components:

+ + + +

Since we know we need both, we can batch some of the file creation work together with a terminal command. Run this command in your terminal, taking care that you're in the root directory of your app:

+ +
touch src/components/Form.js src/components/FilterButton.js
+ +

The <Form />

+ +

Open components/Form.js and do the following:

+ + + +

Your Form.js file should read like this:

+ +
import React from "react";
+
+function Form(props) {
+  return (
+    <form>
+      <h2 className="label-wrapper">
+        <label htmlFor="new-todo-input" className="label__lg">
+          What needs to be done?
+        </label>
+      </h2>
+      <input
+        type="text"
+        id="new-todo-input"
+        className="input input__lg"
+        name="text"
+        autoComplete="off"
+      />
+      <button type="submit" className="btn btn__primary btn__lg">
+        Add
+      </button>
+    </form>
+  );
+}
+
+export default Form;
+ +

The <FilterButton />

+ +

Do the same things you did to create Form.js inside FilterButton.js, but call the component FilterButton() and copy the HTML for the first button inside the <div> element with the class of filters from App.js into the return statement.

+ +

The file should read like this:

+ +
import React from "react";
+
+function FilterButton(props) {
+  return (
+    <button type="button" className="btn toggle-btn" aria-pressed="true">
+      <span className="visually-hidden">Show </span>
+      <span>all </span>
+      <span className="visually-hidden"> tasks</span>
+    </button>
+  );
+}
+
+export default FilterButton;
+ +
+

Note: You might notice that we are making the same mistake here as we first made for the <Todo /> component, in that each button will be the same. That’s fine! We’re going to fix up this component later on, in Back to the filter buttons.

+
+ +

Importing all our components

+ +

Let's make use of our new components.

+ +

Add some more import statements to the top of App.js, to import them.

+ +

Then, update the return statement of App() so that it renders our components. When you’re done, App.js will read like this:

+ +
import React from "react";
+import Form from "./components/Form";
+import FilterButton from "./components/FilterButton";
+import Todo from "./components/Todo";
+
+function App(props) {
+  const taskList = props.tasks.map(task => (
+    <Todo
+        id={task.id}
+        name={task.name}
+        completed={task.completed}
+        key={task.id}
+      />
+    )
+  );
+  return (
+    <div className="todoapp stack-large">
+      <Form />
+      <div className="filters btn-group stack-exception">
+        <FilterButton />
+        <FilterButton />
+        <FilterButton />
+      </div>
+      <h2 id="list-heading">3 tasks remaining</h2>
+      <ul
+        role="list"
+        className="todo-list stack-large stack-exception"
+        aria-labelledby="list-heading"
+      >
+        {taskList}
+      </ul>
+    </div>
+  );
+}
+
+export default App;
+ +

With this in place, we’re almost ready to tackle some interactivity in our React app!

+ +

Summary

+ +

And that's it for this article — we've gone into some depth on how to break up your app nicely into components, end render them efficiently. Now we'll go on to look at how we handle events in React, and start adding some interactivity.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

In this module

+ + diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html new file mode 100644 index 0000000000..5114539cca --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html @@ -0,0 +1,468 @@ +--- +title: Reactをはじめる +slug: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started +tags: + - Beginner + - Frameworks + - JavaScript + - Learn + - React + - client-side +translation_of: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}
+ +

この記事では React のはじめかたを説明します。Reactの背景と使い方について説明し、ローカル環境で基本的な React ツールチェーンを設定します。また、シンプルな基本アプリを作成して、React がどのようなプロセスで機能するのかを学んでいきます。

+ + + + + + + + + + + + +
前提条件: +

HTMLCSSJavaScript に精通していること、ターミナル/コマンドラインに関する知識があること。

+ +

React は JSX (JavaScript と XML) と呼ばれる HTML-in-JavaScript を使用します。HTML と JavaScript の両方に精通していると、JSX の学習に役立ち、アプリケーションのバグが JavaScript に関連しているか、React のより具体的なドメインに関連しているかを特定するのに役立つます。

+
目的:ローカルの React 開発環境をセットアップし、開始アプリを作成して、それがどのように機能するかの基本を理解する
+ +

React の基礎

+ +

公式のキャッチフレーズにあるように、React はユーザーインターフェイスを構築するためのライブラリーです。React はフレームワークではなく、ウェブに限定されるものでもありません。他のライブラリーと共に使用して、特定の環境にレンダリングしますます。たとえば、React Native はモバイルアプリケーションの構築に使用できます。React 360 を使用して、仮想現実アプリケーションを構築できます。他にも可能性があります。

+ +

ウェブ向けに構築するには、開発者は ReactDOM と連携してリアクトを使用します。リアクトと ReactDOM は、他の本当のウェブ開発フレームワークと同じ土台で議論さんくれ、同じような問題を解決するために用いられます。しかし React を「フレームワーク」と呼ぶとき、私たちはその口語的な理解に別途でいます。

+ +

React が目指すところは、開発者がUIを構築しているときに発生するバグを最小限に抑えることです。これは、コンポーネント (ユーザーインターフェイスの一部を記述する自己完結型の論理的なコード) を使用して行われます。これらのコンポーネントを組み合わせて完全なUIを作成でき、React はレンダリング作業の大部分を抽象化して、UI デザインに集中できるようにします。

+ +

ユースケース

+ +

このモジュールで取り上げられている他のフレームワークとは異なり、React はコード規則やファイル編成に関する厳密なルールを適用しません。これにより、チームは自分に最適な規則を設定し、Reactを好きなように採用することができます。React は、単一のボタン、一部のインターフェース、またはアプリのユーザーインターフェース全体を処理できます。

+ +

React はインターフェイスの一部に適に用することが できます が、jQuery のようなライブラリーや Vue のようなフレームワークほどアプリケーションに「ドロップ」するのは簡単ではありません。React でアプリ全体を構築するのに適しています。

+ +

さらに、JSX のインターフェースの作成など、React アプリの開発者体験にはコンパイルプロセスが必要とします。Babel のようなコンパイラーをウェブサイトに追加すると、コードの実行が遅くなるため、開発者はビルドステップでそのようなツールをセットアップすることがよくあります。間違いなく React には厳しいツール要件がありますが、学習することはできます。

+ +

この記事では、Facebook 独自の create-react-app を使って、アプリケーションのインターフェイスを構築していきます。

+ +

ReactにおけるJavaScriptの書き方

+ +

Reactは、そのパターンの多くに最新の JavaScript の機能を利用しています。JavaScript からの最大の違いは、JSX 構文を使うことです。JSX は JavaScript の構文を拡張して、HTML のようにコードを書くことができます。例えば:

+ +
const heading = <h1>Mozilla Developer Network </h1>;
+ +

この定数 heading は、JSX 式と呼ばれます。React はこのように <h1> タグをレンダリングすることができます。

+ +

セマンティックの観点で、 <header> タグで、見出しを囲みたいとします。JSX では、HTML のように、要素を相互にネストできます。

+ +
const header = (
+  <header>
+    <h1>Mozilla Developer Network</h1>
+  </header>
+);
+ +
+

: このスニペットの括弧は JSX に固有のものではなく、あなたのアプリケーションに影響を与えません。それらは、あなた (またあなたのコンピューター) にとって、内部の複数行のコードが同じ式の一部であるという意味です。次のように header を定義することもできます。

+ +
const header = <header>
+    <h1>Mozilla Developer Network</h1>
+</header>
+ +

ただし、<header> 式を開始するタグが、対応する終了タグと同じ位置にインデントされていないため、これは少し読みにくいかもしれません。

+
+ +

もちろん、あなたのブラウザーはそのままでは JSX を読むことができません。(BabelParcel などのツールを使用して) コンパイルすると、ヘッダー式は次のようになります。

+ +
const header = React.createElement("header"、null、
+  React.createElement("h1"、null、 "Mozilla Developer Network")
+);
+ +

コンパイルステップとコンパイル自体をスキップし、React.createElement() を使って、独自のUIを自分で書くこと。ただし、こうするとJSXの宣言的なメリットが失われ、コードが読みにくくなってしまいます。コンパイルは開発プロセスとは別のステップですが、Reactコミュニティの多くの開発者は、JSXの読みやすさに価値があると考えています。さらに、外部ツールにより、JSX から JavaScript へのコンパイルがセットアッププロセスの一部になります。特段の必要がない限り、コンパイルを自分の手で行う必要はありません。

+ +

JSX は HTML と JavaScript がミックスされたものなので、一部の開発者にとっては直感的に使うことができます。しかしそうでない人にとってはは、そのミックスされていることで混乱させられると言います。ただし、慣れれば、ユーザーインターフェースをより迅速かつ直感的に構築できるようになり、他の人がコードを一目で理解しやすくなります。

+ +

JSX の詳細については、React チームの JSX In Depth の記事をご覧ください。

+ +

最初の React アプリをセットアップする

+ +

React を使用する方法はたくさんありますが、前述のように、コマンドラインインターフェイス (CLI) ツールの create-react-app を使用します。これにより、いくつかのパッケージをインストールしていくつかを作成することにより、React アプリケーションの開発プロセスをスムーズにします。

+ +

<script> を HTML ファイルにコピーすることで create-react-app なしでウェブサイトに React を追加することは可能ですが、create-react-app CLI は、React アプリケーションの一般的な始め方です。これを使うことで、アプリの作成に集中でき、セットアップに煩わされなくなります。

+ +

必要条件

+ +

create-react-app を使用するには、Node.js をインストールする必要があります。長期サポート (LTS) バージョンを使用することをお勧めします。ノードには、npm (ノードパッケージマネージャー) および npx (ノードパッケージランナー) が含まれます。

+ +

代わりに Yarn パッケージマネージャーを使用することもできますが、この一連のチュートリアルでは npm を使用するものとします。npm と yarn の詳細については、パッケージ管理の基本を参照してください。

+ +

Windows を使用している場合、このチュートリアルで言及されている端末コマンドを使用するには、Unix / macOS 端末と同等のソフトウェアをインストールする必要があります。Gitbash (Windows 用git ツールセットの一部として提供) または Linux 用の Windows サブシステム (WSL) の両方が適しています。これら、および一般的な端末コマンドの詳細については、コマンドラインクラッシュコースを参照してください。

+ +

また、React と ReactDOM は、かなり近代的な一連のブラウザー (IE9 以降) でのみ機能するアプリを生成することにも注意してください。これらのチュートリアルを実行するときは、Firefox、Safari、Chrome などの最新のブラウザーを使用することをお勧めします。

+ +

詳細については、以下も参照してください。

+ + + +

アプリの初期化

+ +

create-react-app は引数を 1 つ取ります。アプリに付ける名前です。create-react-app はこの名前を使用して新しいディレクトリーを作成し、その中に必要なファイルを作成します。cd でアプリのハードドライブ上の場所に移動したことを確認してから、ターミナルで次のコマンドを実行します。

+ +
npx create-react-app moz-todo-react
+ +

これは moz-todo-react ディレクトリーを作成し、その中でいくつかのことを行います:

+ + + +
+

: Yarn パッケージマネージャーがインストールされている場合、create-react-app はデフォルトで npm の代わりにそれを使用します。両方のパッケージマネージャーがインストールされていて、明示的に NPM を使用したい場合、create-react-app を実行するときに --use-npm フラグを追加できます。

+ +
npx create-react-app moz-todo-react --use-npm
+
+ +

create-react-app が機能している間、端末にいくつかのメッセージが表示されますが、正常な動作です!これには数分かかる場合がありますので、お茶でも作って待ってみましょう。

+ +

プロセスが完了したら、moz-todo-reactディレクトリーへ cd して、コマンド npm start を実行します。create-react-app によってインストールされたスクリプトは、localhost:3000 のローカルサーバーで提供され始め、新しいブラウザータブでアプリを開きます。ブラウザーには次のように表示されます。

+ +

デフォルトのcreate-react-app アプリケーションを示す、Firefox MacOS のスクリーンショット、localhost:3000を開く

+ +

アプリケーションの構造

+ +

create-react-app は、React アプリケーションの開発に必要なすべてのものを提供します。初期のファイル構造は次のようになります。

+ +
moz-todo-react
+├──README.md
+├──node_modules
+├──package.json
+├──package-lock.json
+├──.gitignore
+├──public
+│├──favicon.ico
+│├──index.html
+│└──manifest.json
+└──src
+    ├──App.css
+    ├──App.js
+    ├──App.test.js
+    ├──index.css
+    ├──index.js
+    ├──logo.svg
+    └──serviceWorker.js
+ +

src ディレクトリーはアプリケーションの実態ともいえるソースことがある場所で、私たちが触るのは主にこの部分です。

+ +

public ディレクトリーには、アプリを開発している間、ブラウザーによって読み込まれるファイルが含まれています。これらの中で最も重要なのは index.html です。React はこのファイルにコードを挿入して、ブラウザーで実行できるようにします。create-react-app 関数に役立つマークアップが他にもいくつかあるので、何をしているのかを理解していなければ、自分で編集しないように注意してください。このファイルの要素内の <title> を変更して、アプリケーション自体のタイトルを反映させる必要があります。アクセシビリティ向上のためには正しいページタイトルが重要です。

+ +

public ディレクトリーは、アプリをビルドしてデプロイするときにも公開されます。このチュートリアルではデプロイ自体については説明しませんが、アプリのデプロイチュートリアルで説明されているものと同様のソリューションを使用できるはずです。

+ +

このpackage.json ファイルには、Node.js / npm がプロジェクトを整理するために使用するプロジェクトに関する情報が含まれています。このファイルは React アプリケーションに固有のものではありません。create-react-app は単にそれを生成します。このチュートリアルを完了するためにこのファイルを理解する必要はまったくありませんが、詳しく知りたい場合は「package.json ファイルとは」を参照してください。

+ +

最初の React コンポーネント— <App/>

+ +

React における、コンポーネントとはアプリの一部をレンダリングする再利用可能なモジュールを指します。これらのパーツは大きくても小さくてもかまいませんが、通常は明確に定義され、単一責務のもとに作られます。

+ +

ブラウザーに表示されているように、src/App.js を開いて編集しましょう。このファイルには、最初のコンポーネント、App、その他の数行のコードが含まれています。

+ +
import React from 'react';
+import logo from './logo.svg';
+import './App.css';
+
+function App() {
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Edit <code>src/App.js</code> and save to reload.
+        </p>
+        <a
+          className="App-link"
+          href="https://reactjs.org"
+          target="_blank"
+          rel="noopener noreferrer"
+        >
+          Learn React
+        </a>
+      </header>
+    </div>
+  );
+}
+export default App;
+ +

この App.js ファイルは 3 つの主要な部分で構成されています。上部にいくつかの宣言されている import、中央にある App、最下部にある export。ほとんどの React コンポーネントはこのように書かれます。

+ +

ステートメントをインポートする

+ +

import はファイルの先頭に宣言され、App.js が他の場所で定義されているコードを使用するのを許可します。これらをさらに詳しく見てみましょう。

+ +
import React from 'react';
+import logo from './logo.svg';
+import './App.css';
+ +

最初のステートメントは、React ライブラリー自体をインポートします。React は、作成する JSX を React.createElement() に変換するため、すべての React コンポーネントが React モジュールをインポートする必要があります。この手順をスキップすると、アプリケーションでエラーが発生します。

+ +

2 番目のステートメントは、'./logo.svg' をインポートします。最初の ./ パスのと最後の拡張子 .svg に注意してください。これらはファイルがローカルであり、JavaScript ファイルではないことを示しています。実際、logo.svg ファイルは src/ ディレクトリーにあります。

+ +

React モジュールのインポート時にパスや拡張子は記述しません—これはローカルファイルではないからです。代わりに、package.json ファイルに依存関係としてリストされます。このレッスンでは、この違いに注意してください。

+ +

3番目のステートメントは、App コンポーネントに関連する CSS をインポートします。変数名も from ディレクティブもないことに注意してください。この特定のインポート構文は、JavaScript モジュール構文に特有のものではありません。Webpack から提供されるものです。create-react-app ツールは、すべての JavaScript ファイルをバンドルしてブラウザーに提供するために使用します。

+ +

App コンポーネント

+ +

import の次に、App という名前の関数があります。ほとんどの JavaScript コミュニティはhelloWorld のようなキャメルケース名を好みますが、React コンポーネントは HelloWorld のようなパスカルケース変数名を使用して、特定のJSX 要素が React コンポーネントであり、通常の HTML タグではないことを明確にしています。App 関数の名前を app に変更すると、ブラウザーにエラーが表示されます。

+ +

アプリをもっと詳しく見てみましょう。

+ +
function App() {
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Edit <code>src/App.js</code> and save to reload.
+        </p>
+        <a
+          className="App-link"
+          href="https://reactjs.org"
+          target="_blank"
+          rel="noopener noreferrer"
+        >
+          Learn React
+        </a>
+      </header>
+    </div>
+  );
+}
+ +

この App 関数は JSX 式を返します。この式には、ブラウザーが最終的に DOM にレンダリングするものを定義します。

+ +

HTML と同じように、attribute="value" のように属性をもつ要素があります。3 行目では、<div> 開始タグに className 属性があります。これは HTML のclass 属性と同じですが、JSX は JavaScript であるため使用できません。class が予約されているためです。つまり、JavaScript ではすでにそれを使用しており、もし同様に使うと問題が発生するということです。同じような理由で、他のいくつかの HTML 属性は、HTML とは異なる方法で JSX で記述されています。

+ +

6 行目の <p> タグを「Hello, world!」に変更して、ファイルを保存します。この変更はブラウザー http://localhost:3000 で実行されている開発サーバーですぐにレンダリングされます。次に、<a> タグを削除して保存します。すると、「Learn React」リンクはなくなります。

+ +

あなたの App コンポーネントは次のようになります。

+ +
function App() {
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Hello, World!
+        </p>
+      </header>
+    </div>
+  );
+}
+ +

ステートメントのエクスポート

+ +

App.js ファイルの一番下にある export default App は、App コンポーネントを他のモジュールで使用できるようにしています。

+ +

index を詳しくみる

+ +

src/index.js を開きましょう。App コンポーネントを使用しているのがわかります。このファイルはアプリのエントリーポイントであり、最初は次のようになっています。

+ +
import React from 'react';
+import ReactDOM from 'react-dom';
+import './index.css';
+import App from './App';
+import * as serviceWorker from './serviceWorker';
+
+ReactDOM.render(<App />, document.getElementById('root'));
+
+// If you want your app to work offline and load faster, you can change
+// unregister() to register() below. Note this comes with some pitfalls.
+// Learn more about service workers: https://bit.ly/CRA-PWA
+serviceWorker.unregister();
+ +

App.js と同様に、ファイルは、実行する必要のあるすべての JS モジュールとその他のアセットをインポートすることから始まります。src/index.css ではアプリ全体に適用されるグローバルスタイルを保持します。ここに、インポートされたAppコンポーネントも確認できます。下部の export により、App.js がインポートできるようになりました。

+ +

7 行目 ReactDOM.render() は 2 つの引数で React の関数を呼び出します:

+ + + +

これらはすべて、App コンポーネントを最初のコンポーネントとして React アプリケーションをレンダリングすることを React に伝えます。

+ +
+

: JSX では、React コンポーネントと HTML 要素には閉じスラッシュが必要です。そのまま <App> または <img> と書くとエラーが発生します。

+
+ +

Service Worker は、アプリケーションのパフォーマンスを向上させ、ウェブアプリケーションの機能をオフラインで動作させることができる興味深いコードですが、この記事の対象ではありません。5 行目と 9 〜 12 行目を削除します。

+ +

最終的なindex.jsファイルは次のようになります。

+ +
import React from 'react';
+import ReactDOM from 'react-dom';
+import './index.css';
+import App from './App';
+
+ReactDOM.render(<App />, document.getElementById('root'));
+ +

変数と props

+ +

次に、JavaScript スキルのいくつかを使用して、コンポーネントの編集と React でのデータの操作をもう少し快適にします。JSX内での変数の使用方法について説明し、データをコンポーネントに渡す方法である props を紹介します (その後、変数を使用してアクセスできます)。

+ +

JSXの変数

+ +

App.js に戻り、9 行目に注目しましょう。

+ +
<img src = {logo} className = "App-logo" alt = "logo" />
+ +

ここでは、<img /> タグの src 属性値は中括弧で囲まれています。これは、JSX が変数を認識する方法です。React が {logo} を表示し、アプリの2行目のインポートを参照していることを確認してから、logo ファイルを取得してレンダリングします。

+ +

独自の変数を作ってみましょう。App の return ステートメントの前に const subject = 'React'; を追加します。すると、App コンポーネントは次のようになります。

+ +
function App() {
+  const subject = "React";
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Hello, World!
+        </p>
+      </header>
+    </div>
+  );
+}
+ +

次のように、8 行目を変更して「world」という単語の代わりに subject 変数を使用します。

+ +
function App() {
+  const subject = "React";
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Hello, {subject}!
+        </p>
+      </header>
+    </div>
+  );
+}
+ +

保存すると、「Hello、world!」の代わりにブラウザーに「Hello、React!」と表示されます。

+ +

変数は便利ですが、設定したばかりの変数はReactの機能をあまり活用していません。そこで、propsの登場です。

+ +

コンポーネントのprops

+ +

props はコンポーネントに渡される任意のデータです。prop はコンポーネント内に記述され、HTML属性と同じ構文を使用します — prop="value"index.jsを開き、<App/> に最初の prop を渡しましょう。

+ +

<App/> コンポーネントに subject という prop を追加して、値は Clarice とします。完了すると、コードは次のようになります。

+ +
ReactDOM.render(<App subject="Clarice" />, document.getElementById('root'));
+ +

App.js に戻り、App 関数自体をもう一度見てみましょう。この関数は次のようになっています (簡潔にするために return で短くしています)。

+ +
function App() {
+  const subject = "React";
+  return (
+    // return statement
+  );
+}
+ +

App 関数の引数を変更して、props をパラメーターとして受け入れられるようにします。他のパラメーターと同様 props に、console.log() を入力して、ブラウザーのコンソールにそれを表示させます。すると、次のようになります。

+ +
function App(props) {
+  const subject = "React";
+  console.log(props);
+  return (
+    // return statement
+  );
+}
+ +

ファイルを保存し、ブラウザーの JavaScript コンソールを確認します。次のようなログが表示されるはずです。

+ +
Object { subject: "Clarice" }
+ +

オブジェクトプロパティ subject は、<App /> コンポーネント呼び出しに追加した subject プロパティに対応し、文字列 Clarice はその値に対応します。React のコンポーネントプロップは、常にこのようにオブジェクトに集約されます。

+ +

subject は props の一部です。App.js でこれを使ってみましょう。subject 定数を変更して、React という文字列として定義する代わりに props.subject の値を読み取るようにします。console.log() は必要に応じて削除することもできます。

+ +
function App(props) {
+  const subject = props.subject;
+  return (
+    // return statement
+  );
+}
+ +

保存すると、アプリは「Hello、Clarice!」と挨拶するはずです。index.js に戻り、subject の値を編集して保存すると、テキストが変更されます。

+ +

まとめ

+ +

これで、React をローカルでインストールする方法、スターターアプリを作成する方法、基本的にどのように機能するかなど、React の入門が終わりました。次の記事では、最初に適したアプリケーションである todo リストの作成を開始します。ただし、その前に、私たちが学んだことのいくつかをおさらいしましょう。

+ +

React では:

+ + + +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html new file mode 100644 index 0000000000..debc627272 --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html @@ -0,0 +1,599 @@ +--- +title: React ToDoリストをはじめる +slug: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning +translation_of: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning +--- +
+

{{LearnSidebar}}

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+
+ +

たとえば、Reactで概念実証を作成する必要があるとします。これは、ユーザーが作業したいタスクを追加、編集、削除したり、タスクを削除せずに完了としてマークしたりできるアプリです。この記事では、基本的なAppコンポーネントの構造とスタイルを設定し、個々のコンポーネントの定義と変更に対応できるようにします。これについては後で追加します。

+ +
+

:コードをGoogleのバージョンと照合する必要がある場合は、todo-reactリポジトリでサンプルのReactアプリコードの完成版を見つけることができます。実行中のバージョンについては、https://mdn.github .io / todo-react-build /を参照してください。

+
+ + + + + + + + + + + + +
前提条件: +

コアHTMLCSSJavaScriptの言語に精通していることターミナル/マンドコラインに関すてる知識

+
目的:todoリストのケーススタディを紹介し、基本的なApp構造とスタイルを整える。
+ +

アプリの「ユーザーストーリー」

+ +

ソフトウェア開発では、ユーザーストーリーはユーザーの観点から実行可能な目標を指します。作業を開始する前にユーザーストーリーを定義すると、作業に集中することができます。今回、私たちのアプリは以下のストーリーを実現する必要があります:

+ +

ユーザーができること

+ + + +

これらのストーリーに1つずつ取り組みます。

+ +

プロジェクトに入る前に現状整理

+ +

create-react-appは、プロジェクトでまったく使用しないファイルをいくつか作成しています。

+ + + +

次に、以下のコマンドをコピーしてターミナルに貼り付け、不要なファイルをいくつか削除します。アプリのルートディレクトリから開始していることを確認してください。

+ +
# Move into the src directory of your project
+cd src
+# Delete a few files
+rm -- App.test.js App.css logo.svg serviceWorker.js setupTests.js
+# Move back up to the root of the project
+cd ..
+ +

ノート:

+ + + +

はじめのプロジェクトコード

+ +

このプロジェクトの開始点として、次の2つを提供します。現在持っているものを置き換えるApp関数と、アプリのスタイルを設定するCSSです。

+ +

JSX

+ +

次のスニペットをクリップボードにコピーして貼り付けApp.js、既存のApp()関数を置き換えます。

+ +
function App(props) {
+  return (
+    <div className="todoapp stack-large">
+      <h1>TodoMatic</h1>
+      <form>
+        <h2 className="label-wrapper">
+          <label htmlFor="new-todo-input" className="label__lg">
+            What needs to be done?
+          </label>
+        </h2>
+        <input
+          type="text"
+          id="new-todo-input"
+          className="input input__lg"
+          name="text"
+          autoComplete="off"
+        />
+        <button type="submit" className="btn btn__primary btn__lg">
+          Add
+        </button>
+      </form>
+      <div className="filters btn-group stack-exception">
+        <button type="button" className="btn toggle-btn" aria-pressed="true">
+          <span className="visually-hidden">Show </span>
+          <span>all</span>
+          <span className="visually-hidden"> tasks</span>
+        </button>
+        <button type="button" className="btn toggle-btn" aria-pressed="false">
+          <span className="visually-hidden">Show </span>
+          <span>Active</span>
+          <span className="visually-hidden"> tasks</span>
+        </button>
+        <button type="button" className="btn toggle-btn" aria-pressed="false">
+          <span className="visually-hidden">Show </span>
+          <span>Completed</span>
+          <span className="visually-hidden"> tasks</span>
+        </button>
+      </div>
+      <h2 id="list-heading">
+        3 tasks remaining
+      </h2>
+      <ul
+        role="list"
+        className="todo-list stack-large stack-exception"
+        aria-labelledby="list-heading"
+      >
+        <li className="todo stack-small">
+          <div className="c-cb">
+            <input id="todo-0" type="checkbox" defaultChecked={true} />
+            <label className="todo-label" htmlFor="todo-0">
+              Eat
+            </label>
+          </div>
+          <div className="btn-group">
+            <button type="button" className="btn">
+              Edit <span className="visually-hidden">Eat</span>
+            </button>
+            <button type="button" className="btn btn__danger">
+              Delete <span className="visually-hidden">Eat</span>
+            </button>
+          </div>
+        </li>
+        <li className="todo stack-small">
+          <div className="c-cb">
+            <input id="todo-1" type="checkbox" />
+            <label className="todo-label" htmlFor="todo-1">
+              Sleep
+            </label>
+          </div>
+          <div className="btn-group">
+            <button type="button" className="btn">
+              Edit <span className="visually-hidden">Sleep</span>
+            </button>
+            <button type="button" className="btn btn__danger">
+              Delete <span className="visually-hidden">Sleep</span>
+            </button>
+          </div>
+        </li>
+        <li className="todo stack-small">
+          <div className="c-cb">
+            <input id="todo-2" type="checkbox" />
+            <label className="todo-label" htmlFor="todo-2">
+              Repeat
+            </label>
+          </div>
+          <div className="btn-group">
+            <button type="button" className="btn">
+              Edit <span className="visually-hidden">Repeat</span>
+            </button>
+            <button type="button" className="btn btn__danger">
+              Delete <span className="visually-hidden">Repeat</span>
+            </button>
+          </div>
+        </li>
+      </ul>
+    </div>
+  );
+}
+ +

次にpublic/index.htmlを開いて<title>要素のテキストを開いTodoMaticに変更します。こうすることでアプリ上部の<h1>と一致します。

+ +
<title>TodoMatic</title>
+ +

ブラウザが更新されると、次のように表示されます。

+ +

todo-maticアプリ、スタイルなし、乱雑なラベル、入力、ボタンの混乱を表示

+ +

まだ見た目が整っていなくて、機能もしていませんが、一旦問題はありません。すぐにスタイルを設定します。まず、このJSXと、それがユーザーストーリーにどのように対応するかを考えます。

+ + + +

このフォームによりタスクを作成できます。また、ボタンでフィルタリングもできます。見出しとリストは、それらを読むためのものです現在のところ、タスクを編集するためのUIはあまりよくありません。大丈夫です。後ほど書き足していきます。

+ +

アクセシビリティ

+ +

ここでいくつかの変わった属性に気付くかもしれません。例えば:

+ +
<button type="button" className="btn toggle-btn" aria-pressed="true">
+  <span className="visually-hidden">Show </span>
+  <span>all</span>
+  <span className="visually-hidden"> tasks</span>
+</button>
+ +

ここでは、aria-pressedボタンは2つの状態のいずれかであることができることを(スクリーンリーダーなど)技術的に伝えます(pressedunpressed)onoffの切替のように考えられます。trueの値を設定すると、デフォルトでボタンが押されます。

+ +

CSSが含まれていないため、このvisually-hiddenクラスはまだ意味がありません。ただし、スタイルを設定すると、このクラスの要素はすべて、目の見えるユーザーからは隠され、スクリーンリーダーのユーザーは引き続き使用できます。これは、目の見えるユーザーがこれらの単語を必要としないためです。それらは、ボタンを使用してスクリーンリーダーのユーザーに役立つ追加の視覚的コンテキストがないユーザーのために、ボタンの機能に関する詳細情報を提供するためにあります。

+ +

さらに下には<ul>要素があります

+ +
<ul
+  role="list"
+  className="todo-list stack-large stack-exception"
+  aria-labelledby="list-heading"
+>
+ +

role属性は、タグが表す要素の種類を説明するのに役立ちます。<ul>はデフォルトではリストのように扱われますが、これから追加するスタイルはその機能を壊します。この役割は、<ul>  要素の「リスト」の意味を復元します。これが必要な理由について詳しく知りたい場合は、Scott O'Haraの記事「Fixing Lists」チェックしてください

+ +

このaria-labelledby属性は、リストの見出しをその下にあるリストの目的を説明するラベルとして扱っていることを伝えます。この関連付けを行うと、リストの情報が豊富になり、スクリーンリーダーを通じてユーザーがリストの目的を理解しやすくなります。

+ +

最後に、リスト項目のラベルと入力には、JSXに固有のいくつかの属性があります。

+ +
<input id="todo-0" type="checkbox" defaultChecked={true} />
+<label className="todo-label" htmlFor="todo-0">
+  Eat
+</label>
+ +

<input/ >タグdefaultChecked属性は、デフォルトでこのチェックボックスをチェックするようにReactに指示します。通常のHTMLの場合と同様に、checkedを使用すると、Reactは、チェックボックスでのイベントの処理に関する警告をブラウザーコンソールに表示しますが、これは望ましくありません。とりあえず、これについてあまり心配しないでください。後でイベントを使用するときにこれについて説明します。

+ +

このhtmlFor属性は、HTMLで使用されるfor属性に対応しています。forは予約語であるため、JSXでは属性として使用できません。そのためReactはforの代わりにhtmlForを使用します。

+ +

ノート:

+ + + +

スタイルを実装する

+ +

次のCSSコードをに貼り付けて、src/index.css現在あるものを置き換えます。

+ +
/* RESETS */
+*,
+*::before,
+*::after {
+  box-sizing: border-box;
+}
+*:focus {
+  outline: 3px dashed #228bec;
+  outline-offset: 0;
+}
+html {
+  font: 62.5% / 1.15 sans-serif;
+}
+h1,
+h2 {
+  margin-bottom: 0;
+}
+ul {
+  list-style: none;
+  padding: 0;
+}
+button {
+  border: none;
+  margin: 0;
+  padding: 0;
+  width: auto;
+  overflow: visible;
+  background: transparent;
+  color: inherit;
+  font: inherit;
+  line-height: normal;
+  -webkit-font-smoothing: inherit;
+  -moz-osx-font-smoothing: inherit;
+  -webkit-appearance: none;
+}
+button::-moz-focus-inner {
+  border: 0;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+  font-family: inherit;
+  font-size: 100%;
+  line-height: 1.15;
+  margin: 0;
+}
+button,
+input {
+  overflow: visible;
+}
+input[type="text"] {
+  border-radius: 0;
+}
+body {
+  width: 100%;
+  max-width: 68rem;
+  margin: 0 auto;
+  font: 1.6rem/1.25 Arial, sans-serif;
+  background-color: #f5f5f5;
+  color: #4d4d4d;
+}
+@media screen and (min-width: 620px) {
+  body {
+    font-size: 1.9rem;
+    line-height: 1.31579;
+  }
+}
+/*END RESETS*/
+/* GLOBAL STYLES */
+.form-group > input[type="text"] {
+  display: inline-block;
+  margin-top: 0.4rem;
+}
+.btn {
+  padding: 0.8rem 1rem 0.7rem;
+  border: 0.2rem solid #4d4d4d;
+  cursor: pointer;
+  text-transform: capitalize;
+}
+.btn.toggle-btn {
+  border-width: 1px;
+  border-color: #d3d3d3;
+}
+.btn.toggle-btn[aria-pressed="true"] {
+  text-decoration: underline;
+  border-color: #4d4d4d;
+}
+.btn__danger {
+  color: #fff;
+  background-color: #ca3c3c;
+  border-color: #bd2130;
+}
+.btn__filter {
+  border-color: lightgrey;
+}
+.btn__primary {
+  color: #fff;
+  background-color: #000;
+}
+.btn-group {
+  display: flex;
+  justify-content: space-between;
+}
+.btn-group > * {
+  flex: 1 1 49%;
+}
+.btn-group > * + * {
+  margin-left: 0.8rem;
+}
+.label-wrapper {
+  margin: 0;
+  flex: 0 0 100%;
+  text-align: center;
+}
+.visually-hidden {
+  position: absolute !important;
+  height: 1px;
+  width: 1px;
+  overflow: hidden;
+  clip: rect(1px 1px 1px 1px);
+  clip: rect(1px, 1px, 1px, 1px);
+  white-space: nowrap;
+}
+[class*="stack"] > * {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+.stack-small > * + * {
+  margin-top: 1.25rem;
+}
+.stack-large > * + * {
+  margin-top: 2.5rem;
+}
+@media screen and (min-width: 550px) {
+  .stack-small > * + * {
+    margin-top: 1.4rem;
+  }
+  .stack-large > * + * {
+    margin-top: 2.8rem;
+  }
+}
+.stack-exception {
+  margin-top: 1.2rem;
+}
+/* END GLOBAL STYLES */
+.todoapp {
+  background: #fff;
+  margin: 2rem 0 4rem 0;
+  padding: 1rem;
+  position: relative;
+  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 2.5rem 5rem 0 rgba(0, 0, 0, 0.1);
+}
+@media screen and (min-width: 550px) {
+  .todoapp {
+    padding: 4rem;
+  }
+}
+.todoapp > * {
+  max-width: 50rem;
+  margin-left: auto;
+  margin-right: auto;
+}
+.todoapp > form {
+  max-width: 100%;
+}
+.todoapp > h1 {
+  display: block;
+  max-width: 100%;
+  text-align: center;
+  margin: 0;
+  margin-bottom: 1rem;
+}
+.label__lg {
+  line-height: 1.01567;
+  font-weight: 300;
+  padding: 0.8rem;
+  margin-bottom: 1rem;
+  text-align: center;
+}
+.input__lg {
+  padding: 2rem;
+  border: 2px solid #000;
+}
+.input__lg:focus {
+  border-color: #4d4d4d;
+  box-shadow: inset 0 0 0 2px;
+}
+[class*="__lg"] {
+  display: inline-block;
+  width: 100%;
+  font-size: 1.9rem;
+}
+[class*="__lg"]:not(:last-child) {
+  margin-bottom: 1rem;
+}
+@media screen and (min-width: 620px) {
+  [class*="__lg"] {
+    font-size: 2.4rem;
+  }
+}
+.filters {
+  width: 100%;
+  margin: unset auto;
+}
+/* Todo item styles */
+.todo {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+}
+.todo > * {
+  flex: 0 0 100%;
+}
+.todo-text {
+  width: 100%;
+  min-height: 4.4rem;
+  padding: 0.4rem 0.8rem;
+  border: 2px solid #565656;
+}
+.todo-text:focus {
+  box-shadow: inset 0 0 0 2px;
+}
+/* CHECKBOX STYLES */
+.c-cb {
+  box-sizing: border-box;
+  font-family: Arial, sans-serif;
+  -webkit-font-smoothing: antialiased;
+  font-weight: 400;
+  font-size: 1.6rem;
+  line-height: 1.25;
+  display: block;
+  position: relative;
+  min-height: 44px;
+  padding-left: 40px;
+  clear: left;
+}
+.c-cb > label::before,
+.c-cb > input[type="checkbox"] {
+  box-sizing: border-box;
+  top: -2px;
+  left: -2px;
+  width: 44px;
+  height: 44px;
+}
+.c-cb > input[type="checkbox"] {
+  -webkit-font-smoothing: antialiased;
+  cursor: pointer;
+  position: absolute;
+  z-index: 1;
+  margin: 0;
+  opacity: 0;
+}
+.c-cb > label {
+  font-size: inherit;
+  font-family: inherit;
+  line-height: inherit;
+  display: inline-block;
+  margin-bottom: 0;
+  padding: 8px 15px 5px;
+  cursor: pointer;
+  touch-action: manipulation;
+}
+.c-cb > label::before {
+  content: "";
+  position: absolute;
+  border: 2px solid currentColor;
+  background: transparent;
+}
+.c-cb > input[type="checkbox"]:focus + label::before {
+  border-width: 4px;
+  outline: 3px dashed #228bec;
+}
+.c-cb > label::after {
+  box-sizing: content-box;
+  content: "";
+  position: absolute;
+  top: 11px;
+  left: 9px;
+  width: 18px;
+  height: 7px;
+  transform: rotate(-45deg);
+  border: solid;
+  border-width: 0 0 5px 5px;
+  border-top-color: transparent;
+  opacity: 0;
+  background: transparent;
+}
+.c-cb > input[type="checkbox"]:checked + label::after {
+  opacity: 1;
+}
+ +

保存してブラウザーを確認すると、アプリに適切なスタイルが設定されているはずです。

+ +

まとめ

+ +

これで、todoリストアプリはまるで実際のアプリのように見えます。問題は、実際には何も動かないことです。次の章で修正を始めます!

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

In this module

+ + + + diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html new file mode 100644 index 0000000000..4277a7ba9d --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html @@ -0,0 +1,301 @@ +--- +title: Getting started with Vue +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started +tags: + - Beginner + - Frameworks + - Installation + - JavaScript + - Learn + - client-side + - vue +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}
+ +

Now let's introduce Vue, the third of our frameworks. In this article we'll look at a little bit of Vue background, learn how to install it and create a new project, study the high-level structure of the whole project and an individual component, see how to run the project locally, and get it prepared to start building our example.

+ + + + + + + + + + + + +
前提条件: +

Familiarity with the core HTML, CSS, and JavaScript languages, knowledge of the terminal/command line.

+ +

Vue components are written as a combination of JavaScript objects that manage the app's data and an HTML-based template syntax that maps to the underlying DOM structure. For installation, and to use some of the more advanced features of Vue (like Single File Components or render functions), you'll need a terminal with node + npm installed.

+
Objective:To setup a local Vue development environment, create a starter app, and understand the basics of how it works.
+ +

より明確な Vue

+ +

Vue is a modern JavaScript framework that provides useful facilities for progressive enhancement — unlike many other frameworks, you can use Vue to enhance existing HTML. This lets you use Vue as a drop-in replacement for a library like JQuery.

+ +

That being said, you can also use Vue to write entire Single Page Applications (SPAs). This allows you to create markup managed entirely by Vue, which can improve developer experience and performance when dealing with complex applications. It also allows you to take advantage of libraries for client-side routing and state management when you need to. Additionally, Vue takes a "middle ground" approach to tooling like client-side routing and state management. While the Vue core team maintains suggested libraries for these functions, they are not directly bundled into Vue. This allows you to select a different routing/state management library if they better fit your application.

+ +

In addition to allowing you to progressively integrate Vue into your applications, Vue also provides a progressive approach to writing markup. Like most frameworks, Vue lets you create reusable blocks of markup via components. Most of the time, Vue components are written using a special HTML template syntax. When you need more control than the HTML syntax allows, you can write JSX or plain JavaScript functions to define your  components.

+ +

As you work through this tutorial, you might want to keep the Vue guide and API documentation open in other tabs, so you can refer to them if you want more information on any sub topic.
+ For a good (but potentially biased) comparison between Vue and many of the other frameworks, see Vue Docs: Comparison with Other Frameworks.

+ +

取り付け

+ +

To use Vue in an existing site, you can drop one of the following <script> elements onto a page. This allows you to start using Vue on existing sites, which is why Vue prides itself on being a progressive framework. This is a great option when migrating an existing project using a library like JQuery to Vue. With this method, you can use a lot of the core features of Vue, such as the attributes, custom components, and data-management.

+ + + +

However, this approach has some limitations. To build more complex apps, you’ll want to use the Vue NPM package. This will let you use advanced features of Vue and take advantage of bundlers like WebPack. To make building apps with Vue easier, there is a CLI to streamline the development process. To use the npm package & the CLI you will need:

+ +
    +
  1. Node.js 8.11+ installed.
  2. +
  3. npm or yarn.
  4. +
+ +
+

Note: If you don't have the above installed, find out more about installing npm and Node.js here.

+
+ +

To install the CLI, run the following command in your terminal:

+ +
npm install --global @vue/cli
+ +

Or if you'd prefer to use yarn:

+ +
yarn global add @vue/cli
+ +

Once installed, to initialize a new project you can then open a terminal in the directory you want to create the project in, and run vue create <project-name>. The CLI will then give you a list of project configurations you can use. There are a few preset ones, and you can make your own. These options let you configure things like TypeScript, linting, vue-router, testing, and more.

+ +

We’ll look at using this below.

+ +

新規のプロジェクトを初期化する

+ +

To explore various features of Vue, we will be building up a sample todo list app. We'll begin by using the Vue CLI to create a new app framework to build our app into. Follow the steps below:

+ +
    +
  1. In terminal, cd to where you'd like to create your sample app, then run vue create moz-todo-vue.
  2. +
  3. Use the arrow keys and Enter to select the "Manually select features" option.
  4. +
  5. The first menu you’ll be presented with allows you to choose which features you want to include in your project. Make sure that "Babel" and "Linter / Formatter" are selected. If they are not, use the arrow keys and the space bar to toggle them on. Once they are selected, press Enter to proceed.
  6. +
  7. Next you’ll select a config for the linter / formatter. Navigate to "Eslint with error prevention only" and hit Enter again. This will help us catch common errors, but not be overly opinionated.
  8. +
  9. Next you are asked to configure what kind of automated linting we want. Select "Lint on save". This will check for errors when we save a file inside the project. Hit Enter to continue.
  10. +
  11. Now, you will select how we want your config files to be managed. "In dedicated config files" will put your config settings for things like ESLint into their own, dedicated files. The other option, "In package.json", will put all of your config settings into the app's package.json file. Select "In dedicated config files" and push Enter.
  12. +
  13. Finally, you are asked if you want to save this as a preset for future options. This is entirely up to you. If you like these settings over the existing presets and want to use them again, type y , otherwise type n.
  14. +
+ +

The CLI will now begin scaffolding out your project, and installing all of your dependencies.

+ +

If you've never run the Vue CLI before, you'll get one more question — you'll be asked to choose a package manager. You can use the arrow keys to select which one you prefer. The Vue CLI will default to this package manager from now on. If you need to use a different package manager after this, you can pass in a flag --packageManager=<package-manager>, when you run vue create.  So if you wanted to create the moz-todo-vue project with npm and you'd previously chosen yarn, you’d run vue create moz-todo-vue --packageManager=npm.

+ +
+

Note: We've not gone over all of the options here, but you can find more information on the CLI in the Vue docs.

+
+ +

プロジェクトの構造

+ +

If everything went successfully, the CLI should have created a series of files and directories for your project. The most significant ones are as follows:

+ + + +
+

Note: Depending on the options you select when creating a new project, there might be other directories present (for example, if you choose a router, you will also have a views directory).

+
+ +

.vue ファイル (単一ファイルコンポーネント)

+ +

Like in many front-end frameworks, components are a central part of building apps in Vue. These components let you break a large application into discrete building blocks that can be created and managed separately, and transfer data between each other as required. These small blocks can help you reason about and test your code.

+ +

While some frameworks encourage you to separate your template, logic, and styling code into separate files, Vue takes the opposite approach. Using Single File Components, Vue lets you group your templates, corresponding script, and CSS all together in a single file ending in .vue. These files are processed by a JS build tool (such as Webpack), which means you can take advantage of build-time tooling in your project. This allows you to use tools like Babel, TypeScript, SCSS and more to create more sophisticated components.

+ +

As a bonus, projects created with the Vue CLI are configured to use .vue files with Webpack out of the box. In fact, if you look inside the src folder in the project we created with the CLI, you'll see your first .vue file: App.vue.

+ +

Let's explore this now.

+ +

App.vue

+ +

Open your App.vue file — you’ll see that it has three parts: <template>, <script>, and <style>, which contain the component’s template, scripting, and styling information. All Single File Components share this same basic structure.

+ +

<template> contains all the markup structure and display logic of your component. Your template can contain any valid HTML, as well as some Vue-specific syntax that we'll cover later.

+ +
+

Note: By setting the lang attribute on the <template> tag, you can use Pug template syntax instead of standard HTML — <template lang="pug">. We'll stick to standard HTML through this tutorial, but it is worth knowing that this is possible.

+
+ +

<script> contains all of the non-display logic of your component. Most importantly, your <script> tag needs to have a default exported JS object. This object is where you locally register components, define component inputs (props), handle local state, define methods, and more. Your build step will process this object and transform it (with your template) into a Vue component with a render() function.

+ +

In the case of App.vue, our default export sets the name of the component to app and registers the HelloWorld component by adding it into the components property. When you register a component in this way, you're registering it locally. Locally registered components can only be used inside the components that register them, so you need to import and register them in every component file that uses them. This can be useful for bundle splitting/tree shaking since not every page in your app necessarily needs every component.

+ +
import HelloWorld from './components/HelloWorld.vue';
+
+export default {
+  name: 'app',
+  components: {
+    //You can register components locally here.
+    HelloWorld
+  }
+};
+ +
+

Note: If you want to use TypeScript syntax, you need to set the lang attribute on the <script> tag to signify to the compiler that you're using TypeScript — <script lang="ts">.

+
+ +

<style> is where you write your CSS for the component. If you add a scoped attribute — <style scoped> — Vue will scope the styles to the contents of your SFC. This works similar to CSS-in-JS solutions, but allows you to just write plain CSS.

+ +
+

Note: If you select a CSS pre-processor when creating the project via the CLI, you can add a lang attribute to the <style> tag so that the contents can be processed by Webpack at build time. For example, <style lang="scss"> will allow you to use SCSS syntax in your styling information.

+
+ +

アプリをローカルで実行する

+ +

The Vue CLI comes with a built-in development server. This allows you to run your app locally so you can test it easily without needing to configure a server yourself. The CLI adds a serve command to the project’s package.json file as an npm script, so you can easily run it.

+ +

In your terminal, try running npm run serve (or yarn serve if you prefer yarn). Your terminal should output something like the following:

+ +
INFO  Starting development server...
+98% after emitting CopyPlugin
+
+ DONE  Compiled successfully in 18121ms
+
+  App running at:
+  - Local:   <http://localhost:8080/>
+  - Network: <http://192.168.1.9:8080/>
+
+  Note that the development build is not optimized.
+  To create a production build, run npm run build.
+ +

If you navigate to the “local” address in a new browser tab (this should be something like http://localhost:8080 as stated above, but may vary based on your setup), you should see your app. Right now, it should contain a welcome message, a link to the Vue documentation, links to the plugins you added when you initialized the app with your CLI, and some other useful links to the Vue community and ecosystem.

+ +

default vue app render, with vue logo, welcome message, and some documentation links

+ +

いくつかの変更を加える

+ +

Let's make our first change to the app — we’ll delete the Vue logo. Open the App.vue file, and delete the <img> element from the template section:

+ +
<img alt="Vue logo" src="./assets/logo.png">
+ +

If your server is still running, you should see the logo removed from the rendered site almost instantly. Let’s also remove the HelloWorld component from our template.

+ +

First of all delete this line:

+ +
<HelloWorld msg="Welcome to Your Vue.js App"/>
+ +

If you save your App.vue file now, the rendered app will throw an error because we’ve registered the component but are not using it. We also need to remove the lines from inside the <script> element that import and register the component:

+ +

Delete these lines now:

+ +
import HelloWorld from './components/HelloWorld.vue'
+ +
components: {
+  HelloWorld
+}
+ +

Your rendered app should no longer show an error, just a blank page, as we currently have no visible content inside <template>.

+ +

Let’s add a new <h1> inside <div id="app">. Since we’re going to be creating a todo list app below, let's set our header text to "To-Do List". Add it like so:

+ +
<template>
+  <div id="app">
+    <h1>To-Do List</h1>
+  </div>
+</template>
+ +

App.vue will now show our heading, as you'd expect.

+ +

概要

+ +

Let's leave this here for now. We've learnt about some of the ideas behind Vue, created some scaffolding for our example app to live inside, inspected it, and made a few preliminary changes.

+ +

With a basic introduction out of the way, we'll now go further and build up our sample app, a basic Todo list application that allows us to store a list of items, check them off when done, and filter the list by all, complete, and incomplete todos.

+ +

In the next article we'll build our first custom component, and look at some important concepts such as passing props into it and saving its data state.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

このモジュールでは

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html new file mode 100644 index 0000000000..26f98c400f --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html @@ -0,0 +1,624 @@ +--- +title: よくあるアクセシビリティの問題を扱う +slug: Learn/Tools_and_testing/Cross_browser_testing/Accessibility +tags: + - Accessibility + - Article + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Learn + - Testing + - Tools + - cross browser + - keyboard +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Accessibility +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/JavaScript","Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

次に、私たちはアクセシビリティに注意を向け、一般的な問題、簡単なテストの方法、そしてアクセシビリティの問題を見つけるための監査/自動化ツールの使い方を説明します。

+ + + + + + + + + + + + +
前提条件:コア HTMLCSS、および JavaScript 言語に精通していること。 高水準のクロスブラウザーテストの原則の理解。
目的:一般的なアクセシビリティの問題を診断し、それらを修正するための適切なツールとテクニックを使用できるようにすること。
+ +

アクセシビリティとは?

+ +

ウェブ技術のコンテキストでアクセシビリティと言うとき、ほとんどの人は即座にウェブサイトやアプリが障碍のある人にも使えるようにすることを考えます。 例えば、

+ + + +

しかし、アクセシビリティが単に障碍に関するものであると言うのは間違っています。 実際、アクセシビリティの目的は、高性能デスクトップコンピュータを使用しているユーザーだけでなく、できるだけ多くのコンテキストで、できるだけ多くのユーザーがウェブサイトやアプリを使用できるようにすることです。 極端な例には次のものが含まれます。

+ + + +

ある意味では、このモジュール全体がアクセシビリティについてのものです — クロスブラウザーテストは、あなたのサイトができるだけ多くの人々によって使用できることを確認します。 アクセシビリティとは?では、この記事よりも完全かつ徹底的にアクセシビリティを定義します。

+ +

とは言っても、この記事では、クロスブラウザーと障碍のある人々を取り巻く問題のテスト、そして彼らのウェブの使い方について説明します。 モジュール内の他の場所で、レスポンシブデザインパフォーマンスのような他の分野についてはすでに説明しました。

+ +
+

: ウェブ開発における多くのことと同様に、アクセシビリティは 100% 成功したかどうかではありません。 特にサイトが複雑になるにつれて、100% のアクセシビリティを全てのコンテンツに対して達成することはほとんど不可能です。 その代わりに、防御的なコーディングを介して、できるだけ多くの人があなたのコンテンツのできるだけ多くにアクセスできるようにし、ベストプラクティスに従うようにする努力をします。

+
+ +

よくあるアクセシビリティの問題

+ +

このセクションでは、従うべきベストプラクティスと共に、特定の技術と結びつけて、ウェブのアクセシビリティに関して生じる主な問題のいくつかと、サイトが正しい方向に進んでいるかどうかを確認するための簡単なテストについて、詳細を説明します。

+ +
+

: アクセシビリティは道徳的に正しいことであり、ビジネスには適していますし(多くの障碍のあるユーザー、モバイルデバイスのユーザーなどが重要な市場セグメントを提示しています)、ウェブ資産を障碍のある人々がアクセスできないようにすることは、世界の多くの地域で法律にも違反しています。 詳しくはアクセシビリティのガイドラインと法律を読んでください。

+
+ +

HTML

+ +

意味論的 HTML(要素が正しい目的のために使用されているもの)は箱から出してすぐにアクセスできます — そのようなコンテンツは晴眼者でも読めますし(CSS を使用して、テキストを小さくしすぎたり、隠したりするような愚かなことはしないでください)、スクリーンリーダー(文字通りウェブページをユーザーに読み上げるアプリ)などの支援技術でも使用可能になり、他の利点も付与されます。

+ +

意味論的構造

+ +

意味論的 HTML で最も重要なすばやい勝利は、コンテンツに見出しと段落の構造を使用することです。 これは、スクリーンリーダーのユーザーが、必要なコンテンツをすばやく見つけるために文書の見出しを道標として使用する傾向があるためです。 あなたのコンテンツが見出しを持っていない場合、彼らが得るのは、何かを見つけるための道標のないテキストの巨大な壁だけです。 悪い HTML と良いHTML の例としては、

+ +
<font size="7">私の見出し</font>
+<br><br>
+これが私の文書の最初のセクションです。
+<br><br>
+ここにも段落を追加します。
+<br><br>
+<font size="5">私の副見出し</font>
+<br><br>
+これが私の文書の最初のサブセクションです。 私は人々がこのコンテンツを見つけることができるようにしたいです!
+<br><br>
+<font size="5">私の2番目の副見出し</font>
+<br><br>
+これは私のコンテンツの2番目のサブセクションです。 私は最後のものよりも面白いと思います。
+ +
<h1>私の見出し</h1>
+
+<p>これが私の文書の最初のセクションです。</p>
+
+<p>ここにも段落を追加します。</p>
+
+<h2>私の副見出し</h2>
+
+<p>これが私の文書の最初のサブセクションです。 私は人々がこのコンテンツを見つけることができるようにしたいです!</p>
+
+<h2>私の2番目の副見出し</h2>
+
+<p>これは私のコンテンツの2番目のサブセクションです。 私は最後のものよりも面白いと思います。</p>
+ +

さらに、あなたのコンテンツはそのソース順で論理的に意味があるべきです — あなたは後で CSS を使い、いつでもそれを望んだ所に置くことができますが、最初から正しいソース順を手にするべきです。

+ +

テストとして、あなたはサイトの CSS をオフにして、CSS がなければそれがどれほど理解できるか見ることができます。 コードから CSS を取り除くだけでこれを手動で行うことができますが、最も簡単な方法はブラウザー機能を使用することです。 例えば、

+ + + +

ネイティブなキーボード・アクセシビリティを使う

+ +

特定の HTML 機能はキーボードのみを使用して選択できます — これはデフォルトの動作で、ウェブの初期の頃から使用可能です。 この機能を持つ要素は、ユーザーがウェブページと対話することを可能にする一般的なもの、すなわちリンク、{{htmlelement("button")}}、そして {{htmlelement("input")}} のようなフォーム要素です。

+ +

native-keyboard-accessibility.html の例を使ってこれを試すことができます(ソースコードを見る) — これを新しいタブで開いて、そして Tab キーを押してみてください。 数回押すと、タブフォーカスがさまざまなフォーカス可能な要素を通過し始めます。 どの要素がフォーカスされているかわかるように、フォーカスされた要素には全てのブラウザーでハイライトされたデフォルトのスタイルが与えられます(ブラウザーによって若干異なります)。

+ +

+ +

次に Enter / Return を押してフォーカスのあるリンクをたどるか、ボタンを押すか(ボタンにメッセージを知らせるための JavaScript が含まれています)、テキスト入力にテキストを入力するためにタイプし始めることができます(他のフォーム要素には異なるコントロールがあります。 例えば、{{htmlelement("select")}} 要素では、上下の矢印キーを使用してそのオプションを表示したり切り替えたりできます)。

+ +

ブラウザーが異なれば、使用可能なキーボードコントロールオプションも異なることに注意してください。 最近のほとんどのブラウザーは上記のタブパターンに従いますが(フォーカス可能な要素を逆方向に移動するために Shift + Tab を押すこともできます)、次のようにブラウザーによっては独自の特徴があります。

+ + + +
+

重要: あなたが書く新しいページのどれでも、この種のテストを実行するべきです — 機能がキーボードによってアクセスできることを確認してください。

+
+ +

この例では、正しい仕事に正しい意味論的要素を使用することの重要性を強調しています。 任意の要素を、CSS でリンクやボタンのように見せたり、JavaScript でリンクやボタンのように振る舞うようにスタイルすることは可能ですが、実際にはリンクやボタンにはならず、あなたはこれらの要素が無料で与えるアクセシビリティの多くを失うでしょう。 あなたがそれを避けることができるならばしないでください。

+ +

もう1つのヒント — 次の例に示すように、{{cssxref(":focus")}} 疑似クラスを使用して、フォーカス可能要素のフォーカス時の外観をコントロールできます。 フォーカスとホバーのスタイルを倍増するのは良い考えです。 それにより、マウスやキーボードを使用しているかどうかに関わらず、ユーザーがコントロールをアクティブにしたときに何かが行われるという視覚的な手がかりを得ることができます。

+ +
a:hover, input:hover, button:hover, select:hover,
+a:focus, input:focus, button:focus, select:focus {
+  font-weight: bold;
+}
+ +
+

: CSS を使用してデフォルトのフォーカススタイルを取り除く場合は、デザインに適した他のスタイルに置き換えてください — これは非常に有用なアクセシビリティツールであり、取り除くべきではありません。

+
+ +

キーボード・アクセシビリティを組み込む

+ +

時にはキーボード・アクセシビリティを失うことが避けられないこともあります。 意味論的にあまり良くないサイトを継承したかもしれませんし(<div> で作られたボタンを生成する恐ろしい {{glossary("CMS")}} に行き着くかもしれません)、HTML5 の {{htmlelement("video")}} 要素のようにキーボード・アクセシビリティが組み込まれていない複雑なコントロールを使用しているかもしれません(驚くべきことに、Opera は <video> 要素のデフォルトのブラウザーコントロールをタブ操作できる唯一のブラウザーです)。 次のようないくつかの選択肢があります。

+ +
    +
  1. <button> 要素(デフォルトでタブ移動可能)と JavaScript を使用してカスタムコントロールを作成し、それらの機能を関連付けます。 これについての良い例は、クロスブラウザーのビデオプレーヤーの作成を参照してください。
  2. +
  3. JavaScript でキーボードショートカットを作成すると、キーボードの特定のキーを押すことで機能をアクティブにできます。 あらゆる目的に適応できるゲーム関連の例については、デスクトップのマウスとキーボードのコントロールを参照してください。
  4. +
  5. 偽のボタンの振る舞いのために、いくつかの興味深い戦術を使ってください。 例えば、fake-div-buttons.html の例を見てください(ソースコードを見る)。 ここでは、それぞれの属性に tabindex="0" という属性を与えることで(もっと有用な詳細については WebAIM の tabindex の記事(英語)を見てください)、偽の <div> ボタンにフォーカスできるようにしました(タブを介すことも含む)。 これにより、ボタンにタブ移動することはできますが、Enter / Return キーでそれらをアクティブにすることはできません。 そのためには、次のちょっとした JavaScript トリックを追加する必要があります。 +
    document.onkeydown = function(e) {
    +  if(e.keyCode === 13) { // The Enter/Return key
    +    document.activeElement.onclick(e);
    +  }
    +};
    + ここでは、document オブジェクトにリスナーを追加して、キーボードのボタンが押されたことを検出します。 イベントオブジェクトの keyCode プロパティを使ってどのボタンが押されたかをチェックし、Return / Enter と一致するキーコードであれば、document.activeElement.onclick() を使用してボタンの onclick ハンドラに格納されている関数を実行します。 activeElement は現在ページにフォーカスしている要素を与えます。
  6. +
+ +
+

: この手法は、イベントハンドラ・プロパティ(onclick など)を使ってオリジナルのイベントハンドラを設定した場合にのみ機能します。 addEventListener は機能しません。 これは、機能を再構築するための非常に面倒な作業です。 それに他にも問題があるはずです。 そもそも正しい要素を正しい仕事に使うほうがよいでしょう。

+
+ +

代替テキスト

+ +

代替テキストは、アクセシビリティにとって非常に重要です — ある人が視覚障碍または聴覚障碍を抱えているためにコンテンツを見たり聞いたりすることができなくなると、これが問題になります。 最も単純な代替テキストは、控え目な {{htmlattrxref("alt","img")}} 属性で、関連するコンテンツを含む全ての画像に含めるべきです。 これはスクリーンリーダーが拾ってユーザーに読み上げるために、ページ上にその意味と内容をうまく伝える画像の説明を含むべきです。

+ +
+

: 詳しくは、代替テキストをお読みください。

+
+ +

欠落している代替テキストは、アクセシビリティ{{anch("Auditing tools","監査ツール")}}を使用するなど、さまざまな方法でテストできます。

+ +

代替テキストは、動画と音声のコンテンツにとってはもう少し複雑です。 テキストトラック(字幕など)を定義し、動画の再生時にそれらを {{htmlelement("track")}} 要素と WebVTT 形式の形式で表示する方法があります(詳細なチュートリアルについては、HTML5 の動画へのキャプションと字幕の追加を参照してください)。 これらの機能に対するブラウザーの互換性はかなり良いのですが、音声用の代替テキストを提供したり、古いブラウザーをサポートしたりする場合は、ページのどこかや別のページに提示した単純なテキストトランスクリプトをお勧めします。

+ +

要素の関係とコンテキスト

+ +

HTML には、他に存在しない要素間のコンテキストと関係を提供するように設計された特定の機能とベストプラクティスがあります。 最も一般的な3つの例は、リンク、フォームラベル、およびデータ表です。

+ +

アクセス可能なリンクテキストの鍵は、スクリーンリーダーを使用している人々が、ページ上の全てのリンクのリストを引き出すという共通の機能を使用することが多いということです。 この場合、リンクテキストはコンテキスト外で意味を成す必要があります。 例えば、「ここをクリック」、「ここをクリック」などのラベルが付いたリンクのリストは、アクセシビリティにとって本当に悪いものです。 リンクテキストはコンテキスト内でもコンテキスト外でも意味を成すのが得策です。

+ +

次に、フォームの {{htmlelement("label")}} 要素は、フォームをアクセス可能にすることを可能にする中心的な機能の1つです。 フォームの悩みは、各フォーム入力にどのデータを入力するべきかを示すためにラベルが必要なことです。 各ラベルを {{htmlelement("label")}} 内に含めて相方のフォーム入力に明確にリンクする必要があり(各 <label>for 属性値はフォーム要素の id 値と一致する必要があります)、ソース順が完全に論理的ではなくても(これは公平であるべきです)、それは意味があります。

+ +
+

:リンクテキストとフォームラベルの詳細については、わかりやすいテキストラベルを参照してください。

+
+ +

最後に、データ表について簡単に説明します。 基本的なデータ表は非常に簡単なマークアップで書くことができますが(bad-table.html のライブソースを見る)、問題があります — スクリーンリーダーのユーザーがデータのグループとして行や列を関連付ける方法はありません — これを行うには、ヘッダー行がどれであるか、そしてそれらが行、列などを見出ししているかどうかを知る必要があります。 これはそのような表に対しては視覚的にしかできません。

+ +

代わりに punk-bands-complete.html の例(ライブソース)を見ると、表のヘッダー({{htmlelement("th")}} と scope 属性)、{{htmlelement("caption")}} 要素など、いくつかのアクセシビリティ補助機能が働いていることがわかります。

+ +
+

: アクセス可能な表の詳細については、アクセス可能なデータ表を参照してください。

+
+ +

CSS

+ +

CSS は HTML よりもはるかに少ない基本的なアクセシビリティ機能を提供する傾向がありますが、それでも誤って使用された場合、それはアクセシビリティにちょうど同じくらい多くの損害を与えることができます。 CSS に関するアクセシビリティのヒントをいくつかすでに説明しました。

+ + + +

考慮すべき点が他にもいくつかあります。

+ +

色とカラーコントラスト

+ +

ウェブサイトの配色を選択するときは、テキスト(前景)のカラーコントラストが背景色とよく合うことを確認するべきです。 あなたのデザインはかっこいいかもしれませんが、色覚異常のような視覚障碍を持つ人々がコンテンツを読むことができないならば、それは良くありません。 配色に十分なコントラストがあるかどうかチェックするために WebAIM のカラーコントラストチェッカー(英語)のようなツールを使ってください。

+ +

もう1つのヒントは、道標や情報を色だけに頼らないようにすることです。 これは、色が見えない人には良くないでしょう。 例えば、必須のフォームフィールドを赤でマークする代わりに、赤いアスタリスクでマークします。

+ +
+

: コントラスト比が高いと、光沢のある画面を備えたスマートフォンやタブレットを使用している人は誰でも、日光のような明るい環境にいるときにページを読みやすくなります。

+
+ +

コンテンツを隠す

+ +

ビジュアルデザインでは、全てのコンテンツを一度に表示する必要がない多くの実例があります。 例えば、タブ付き情報ボックスの例ソースコードを見る)には3つの情報パネルがありますが、それらを重ねて配置し、それぞれを表示するためにクリックできるタブを提供しています(キーボードからもアクセス可能です — 代わりに TabEnter / Return を使って選択することもできます)。

+ +

+ +

スクリーンリーダーのユーザーは、このことを気にしません — コンテンツのソース順が意味を成す限り幸せで、全てに到達できます。 絶対配置(この例で使用されているような)は一般に視覚効果のためにコンテンツを隠す最も良いメカニズムの1つとして見られます、なぜならそれはスクリーンリーダーがそれに到達するのを止めないからです。

+ +

一方で、スクリーンリーダーからコンテンツを隠すので、{{cssxref("visibility")}}:hidden や {{cssxref("display")}}:none は使用しないでください。 正当な理由があるのでなければ、なぜこのコンテンツをスクリーンリーダーから隠したいのでしょうか。

+ +
+

: スクリーンリーダーのユーザーには見えないコンテンツ(英語)には、このトピックに関するもっと有用な詳細があります。

+
+ +

JavaScript

+ +

JavaScript はアクセシビリティに関して CSS と同じ種類の問題を抱えています — それが悪用されたり、乱用されたりするとアクセシビリティの災害になる可能性があります。 JavaScript に関連するアクセシビリティの問題、主に意味論的 HTML の分野についてはすでに示唆しています — 例えば、リンクやボタンを適切に使用するなど、適切な意味論的 HTML を使用して機能を実装するべきです。 可能であれば、JavaScript コードで <div> 要素を使用して機能を偽造しないでください — エラーが発生しやすく、HTML の無料機能を使用するよりも手間がかかります。

+ +

単純な機能

+ +

一般的に単純な機能は HTML だけで適切に機能するはずです — JavaScript は機能を強化するためにのみ使用されるべきであり、完全には組み込みません。 JavaScript の良い使い方には次のものが含まれます。

+ + + +
+

: WebAIM のアクセス可能な JavaScript(英語)は、アクセス可能な JavaScript の考慮事項に関する有用な詳細をいくつか提供します。

+
+ +

より複雑な JavaScript による実装はアクセシビリティに問題をもたらす可能性があります — できる限りのことをする必要があります。 例えば、WebGL を 100% を使用して書かれた複雑な 3D ゲームを視覚障碍者が利用できるようにすることは期待できませんが、マウス以外のユーザーが使用できるようにキーボードコントロールを実装し、色覚異常のある人にも使えるように配色に十分なコントラストがあるようにすることができます。

+ +

複雑な機能

+ +

アクセシビリティにとって問題となる主な分野の1つは、(日付の選択のような)複雑なフォームコントロールを含む複雑なアプリと、頻繁に増分的に更新される動的コンテンツです。

+ +

ネイティブではない複雑なフォームコントロールは、ネストされた <div> が多数含まれる傾向があり、ブラウザーがデフォルトでそれらをどう処理するかわからないため、問題があります。 自分でそれらを考案しているのなら、それらがキーボードからアクセスできることを確認する必要があります。 何らかのサードパーティ製フレームワークを使用している場合は、利用可能なオプションを慎重に検討して、飛びつく前にそれらがどれほどアクセス可能かを確認してください。 Bootstrap は、アクセシビリティにはかなり適しているように見えます。 例えば、Rhiana Heath による Bootstrap をもう少しアクセス可能にする(英語)では、その問題のいくつかを調べ(主にカラーコントラストに関連した)、いくつかの解決策を検討しています。

+ +

定期的に更新される動的コンテンツは、スクリーンリーダーのユーザーがそれを見逃す可能性があるため、特に突然更新される場合は問題になる可能性があります。 XMLHttpRequest または Fetch を使用して定期的に更新されるメインコンテンツパネルを備えた単一ページのアプリがある場合、スクリーンリーダーのユーザーはそれらの更新を見逃す可能性があります。

+ +

WAI-ARIA

+ +

そのような複雑な機能を使用する必要がありますか、それともごく普通の意味論的 HTML が代わりにやりますか? 複雑なものが必要な場合は、WAI-ARIA(Accessible Rich Internet Applications)を使用することを検討するべきです。 これは、ほとんどのブラウザーやスクリーンリーダーが理解できる複雑なフォームコントロールや更新パネルのような項目に(新しい HTML 属性の形式で)意味論を提供する仕様です。

+ +

複雑なフォームウィジェットを扱うには、さまざまな要素がウィジェット内でどのような役割を担っているか(例えば、タブなのか、タブパネルなのか)を示す role、コントロールが無効かどうかを示す aria-disabled などの ARIA 属性を使う必要があります。

+ +

定期的に更新されるコンテンツのリージョンを扱うには、更新されるリージョンを識別する aria-live 属性を使用できます。 その値は、次のようにスクリーンリーダーがどれほど緊急にそれを読み上げるべきかを示します。

+ + + +

これが一例です。

+ +
<p><span id="LiveRegion1" aria-live="polite" aria-atomic="false"></span></p>
+ +

Freedom Scientific の ARIA(Accessible Rich Internet Applications)のライブリージョン(英語)の例で実行中の例を見ることができます — 強調表示された段落はその内容を10秒ごとに更新し、スクリーンリーダーはユーザーにこれを読み上げるべきです。 ARIA のライブリージョン - Atomic(英語)は別の有用な例を提​​供しています。

+ +

ここでは WAI-ARIA を詳細にカバーするためのスペースはありません。 WAI-ARIA の基本でもっと詳しく学ぶことができます。

+ +

アクセシビリティツール

+ +

今まで(キーボードナビゲーションやカラーコントラストチェッカーのような)いくつかのテストのテクニックを含め、さまざまなウェブ技術に対するアクセシビリティの考慮事項について説明してきました。 次に、アクセシビリティのテストを実行するときに使用できる他のツールを見てみましょう。

+ +

監査ツール

+ +

あなたのウェブページを指さすことができる利用可能な監査ツールがいくつかあります。 それらはページを見て、ページに存在するアクセシビリティ問題のリストを返すでしょう。 例えば次のものが含まれます。

+ + + +

Tenon を使って例を見てみましょう。

+ +
    +
  1. Tenon のホームページ(英語)に行きます。
  2. +
  3. bad-semantics.html の例の URL(または分析したい別のウェブページの URL)をページ上部のテキスト入力に入力して [Analyze Your Webpage] を押します。
  4. +
  5. 次に示すように、error/description のセクションが見つかるまで下にスクロールします。
  6. +
+ +

+ +

また、Tenon をプログラム的に使用するための API と同様に、探索できるいくつかのオプション(ページ上部の近くにある [Show Options] リンクを参照)もあります。

+ +
+

: このようなツールは、アクセシビリティの問題を全て自分で解決するのに十分ではありません。 全体像を把握するには、これらの組み合わせ、知識と経験、ユーザーテストなどが必要です。

+
+ +

自動化ツール

+ +

Deque の aXe ツール(英語)は、前述した監査ツールよりも少しばかり進化しています。 他のものと同様に、ページをチェックしてアクセシビリティエラーを返します。 その最もすぐに役立つ形式は、おそらく次のブラウザー拡張機能です。

+ + + +

これらはブラウザー開発者ツールにアクセシビリティタブを追加します。 例えば、Firefox 用のバージョンをインストールし、それを使用して bad-table.html の例を監査すると、次の結果が得られます。

+ +

+ +

aXe は npm を使ってもインストール可能で、GruntGulp のようなタスクランナー、SeleniumCucumber のような自動化フレームワーク、Jasmin のような単体テストフレームワークなどと統合することができます(やはり、詳細についてはメインの aXe ページ(英語)を参照してください)。

+ +

スクリーンリーダー

+ +

重度の視覚障碍者がウェブをどのように使用しているかに慣れるには、スクリーンリーダーを使ってテストする価値があります。 次のように利用可能なスクリーンリーダーは多数あります。

+ + + +

一般的に、スクリーンリーダーはホストオペレーティングシステム上で動作する独立したアプリで、ウェブページだけでなく他のアプリのテキストも読むことができます。 これは必ずしもそうとは限りませんが(ChromeVox はブラウザーの拡張機能です)、通常はそうです。 スクリーンリーダーは少し異なる方法で動作し、異なるコントロールを持つ傾向があるので、全ての詳細を得るためにはあなたが選んだスクリーンリーダーのドキュメントを参照しなければなりません — と言っても、それらは全て基本的に同じような方法で機能します。

+ +

いくつかの異なるスクリーンリーダーを使っていくつかのテストを行い、それらがどのように機能するのか、またどのようにテストするのかについての一般的な考えを説明しましょう。

+ +
+

: WebAIM のスクリーンリーダーの互換性のための設計(英語)では、スクリーンリーダーの使用方法とスクリーンリーダーに最適な機能についての役立つ情報が提供されています。 いくつかの興味深いスクリーンリーダーの使用統計については、第6回スクリーンリーダーのユーザー調査の結果(英語)も参照してください。

+
+ +

VoiceOver

+ +

VoiceOver(VO)は Mac / iPhone / iPad には無料で含まれているので、あなたが Apple 製品を使っているならそれはデスクトップ/モバイルでテストするのに役に立ちます。 ここでは、MacBook Pro の Mac OS X でテストします。

+ +

オンにするには、Cmd + Fn + F5 を押します。 今までに VO を使ったことがない場合は、ようこそ画面が表示され、そこで VO を起動するかどうかを選択できます。 また、使い方を学ぶためにかなり役に立つチュートリアルを実行することもできます。 再びオフにするには、もう一度 Cmd + Fn + F5 を押します。

+ +
+

: チュートリアルは少なくとも一度は実行するべきです — これは VO を学ぶ上で非常に便利な方法です。

+
+ +

VO がオンになっていると、ディスプレイはほぼ同じに見えますが、画面の左下に、現在選択されている VO に関する情報を含む黒いボックスが表示されます。 現在の選択範囲も黒枠で強調表示されます — この強調表示は VO カーソルと呼ばれます。

+ +

+ +

VO を使用するには、「VO 修飾キー」を多用します — これは、実際の VO キーボードショートカットに加えて、それらを機能させるために押す必要があるキーまたはキーの組み合わせです。 このような修飾キーを使用するのは、スクリーンリーダーに共通で、他のコマンドとコマンドが衝突しないようにするためです。 VO の場合、修飾キーは CapsLock または Ctrl + Option のいずれかです。

+ +

VO にはたくさんのキーボードコマンドがありますので、ここではそれら全てをリストしません。 ウェブページのテストに必要な基本的なものは、次の表のとおりです。 キーボードショートカットでは、VO は「VoiceOver 修飾キー」を意味します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
最も一般的な VoiceOver のキーボードショートカット
キーボードショートカット説明
VO + 矢印キーVO カーソルを上下左右に移動します。
VO + スペースバーVO カーソルで強調表示されている項目を選択/アクティブ化します。 これには、ローター(下記参照)で選択した項目が含まれます。
VO + Shift + 下矢印(HTML の表やフォームなどの)項目のグループ内に入ります。 グループ内に入ると、通常どおり上記のコマンドを使用してそのグループ内の項目を移動して選択できます。
VO + Shift + 上矢印グループから出ます。
VO + C(表内の場合)現在の列のヘッダーを読み上げます。
VO + R(表内の場合)現在の行のヘッダーを読み上げます。
VO + C + C(2つの連続した C)(表内の場合)ヘッダーを含む現在の列全体を読み上げます。
VO + R + R(2つの連続した R)(表内の場合)各セルに対応するヘッダーを含め、現在の行全体を読み上げます。
VO + 左矢印VO + 右矢印(日付の選択や時刻の選択などの一部の水平オプション内の場合)オプション間を移動します。
VO + 上矢印VO + 下矢印(日付の選択や時刻の選択などの一部の水平オプション内の場合)現在のオプションを変更します。
VO + U簡単にナビゲーションできるように、見出し、リンク、フォームコントロールなどのリストを表示するローターを使用します。
VO + 左矢印VO + 右矢印(ローター内の場合)ローターで利用可能な異なるリスト間を移動します。
VO + 上矢印VO + 下矢印(ローター内の場合)現在のローターリスト内の異なる項目間を移動します。
Esc(ローター内の場合)ローターを終了します。
Ctrl(VO が話している場合)読み上げを一時停止/再開します。
VO + Z読み上げの最後の部分をやり直します。
VO + DMac の Dock に入るので、その中で実行するアプリを選択できます。
+ +

これはたくさんのコマンドのように思えますが、慣れればそれほど悪くはありません。 VO は、特定の場所でどのコマンドを使用するかについて定期的に注意を促します。 今は VO で遊びましょう。 その後、{{anch("Screenreader testing","スクリーンリーダーのテスト")}}のセクションで例のいくつかを試してみることができます。

+ +

NVDA

+ +

NVDA は Windows 専用で、インストールする必要があります。

+ +
    +
  1. nvaccess.org からダウンロードしてください。 寄付をするか無料でダウンロードするかを選択できます。 ダウンロードできるようになる前にあなたのメールアドレスを与える必要もあるでしょう。
  2. +
  3. ダウンロードしたら、インストールします — インストーラをダブルクリックし、ライセンスに同意して指示に従います。
  4. +
  5. NVDA を起動するには、プログラムファイル/ショートカットをダブルクリックするか、キーボードショートカットの Ctrl + Alt + N を使用します。 起動すると NVDA にようこそダイアログが表示されます。 ここでは、いくつかのオプションから選択し、次に [OK] ボタンを押して作業を進めます。
  6. +
+ +

これで NVDA はあなたのコンピュータ上でアクティブになります。

+ +

NVDA を使用するには、「NVDA 修飾キー」を多用します — これは、実際の NVDA のキーボードショートカットに加えて、それらを機能させるために押す必要があるキーです。 このような修飾キーを使用するのは、スクリーンリーダーに共通で、他のコマンドとコマンドが衝突しないようにするためです。 NVDA の場合、修飾キーは Insert(デフォルト)、または CapsLock([OK] を押す前に NVDA へようこそダイアログボックスの最初のチェックボックスをオンにして選択できます)のいずれかになります。

+ +
+

: NVDA は、VoiceOver よりも、それがどこにあるのか、また何をしているのかを強調する方法という点では微妙です。 あなたが見出しやリストなどをスクロールしているとき、あなたが選択している項目は一般的に微妙なアウトラインでハイライトされますが、これはいつも全てのことに当てはまるわけではありません。 完全に迷子になった場合は、Ctrl + F5 を押して現在のページを更新し、もう一度上から始めることができます。

+
+ +

NVDA にはたくさんのキーボードコマンドがありますので、ここではそれら全てをリストしません。 ウェブページのテストに必要な基本的なものは、次の表のとおりです。 キーボードショートカットでは、NVDA は「NVDA 修飾キー」を意味します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
最も一般的な NVDA のキーボードショートカット
キーボードショートカット説明
NVDA + Q起動している NVDA を再びオフにします。
NVDA + 上矢印現在行を読み上げます。
NVDA + 下矢印現在位置から読み上げを始めます。
上矢印下矢印、または Shift + TabTabページ内の前/次の項目に移動して、それを読み上げます。
左矢印右矢印現在の項目の前/次の文字に移動して、それを読み上げます。
Shift + HH前/次の見出しに移動して、それを読み上げます。
Shift + KK前/次のリンクに移動して、それを読み上げます。
Shift + DD前/次の文書のランドマーク(<nav> など)に移動して、それを読み上げます。
Shift + 1616前/次の見出し(レベル 1 〜 6)に移動して読み上げます。
Shift + FF前/次のフォーム入力に移動して、それにフォーカスを当てます。
Shift + TT前/次のデータ表に移動して、それにフォーカスを当てます。
Shift + BB前/次のボタンに移動して、ラベルを読み上げます。
Shift + LL前/次のリストに移動して、その最初のリスト項目を読み上げます。
Shift + II前/次のリスト項目に移動して、それを読み上げます。
Enter / Return(リンク/ボタンまたは他のアクティブ化可能項目が選択されている場合)項目をアクティブ化します。
NVDA + スペースバー(フォームが選択されている場合)個々の項目を選択できるようにフォーム内に入るか、すでにフォームに入っている場合はフォームから出ます。
Shift + TabTab(フォーム内の場合)フォーム入力間を移動します。
上矢印下矢印(フォーム内の場合)フォーム入力の値を変更します(選択ボックスなどの場合)。
スペースバー(フォーム内の場合)選択値を選択します。
Ctrl + Alt + 矢印キー(表が選択されている場合)表のセル間を移動します。
+ +

スクリーンリーダーのテスト

+ +

スクリーンリーダーを使用することに慣れてきましたが、スクリーンリーダーがどのようにウェブページの良い機能と悪い機能に対処するかを理解するために、簡単なアクセシビリティテストを行うためにスクリーンリーダーを使用したいと思います。

+ + + +

ユーザーテスト

+ +

上記のように、あなたはあなたのサイトのアクセシビリティ問題を決定するために自動化されたツールだけに頼ることはできません。 テスト計画を立てる際には、可能であればアクセシビリティユーザーグループをいくつか含めることをお勧めします(詳細については、コースの前半のユーザーテストのセクションを参照してください)。 必要に応じて、スクリーンリーダーを使用するユーザー、キーボードを使用するユーザー、聴覚を持たないユーザー、および他のグループも参加してください。

+ +

アクセシビリティテストのチェックリスト

+ +

次のリストは、プロジェクトで推奨されるアクセシビリティテストを確実に実行したことを確認するためのチェックリストです。

+ +
    +
  1. HTML が意味論的にできるだけ正しいことを確認してください。 監査ツールを使用して、それを検証することは良いスタートです。
  2. +
  3. CSS がオフになっているときにコンテンツが意味をなすことを確認してください。
  4. +
  5. 機能がキーボードからアクセス可能であることを確認してください。 TabReturn / Enter などを使ってテストします。
  6. +
  7. テキスト以外のコンテンツに代替テキストがあることを確認してください。 監査ツールはそのような問題を捉えるのに適しています。
  8. +
  9. 適切なチェックツールを使用して、サイトのカラーコントラストが許容範囲内であることを確認してください。
  10. +
  11. 隠されたコンテンツがスクリーンリーダーに見えるようにしてください。
  12. +
  13. 可能な限り JavaScript がなくても機能が使えることを確認してください。
  14. +
  15. 適切な場合は、ARIA を使用してアクセシビリティを向上させます。
  16. +
  17. 監査ツールを通してサイトを運営してください。
  18. +
  19. スクリーンリーダーでテストしてください。
  20. +
  21. あなたが行ったことを言うために、あなたのサイトのどこかに見つけることができるアクセシビリティの方針/声明を含めてください。
  22. +
+ +

助けを探す

+ +

あなたがアクセシビリティに関して遭遇するであろう他の多くの問題があります。 本当に知っておくべき最も重要なことは、オンラインで答えを見つける方法です。 HTML と CSS の記事の助けを探すのセクションを参考にしてください。

+ +

まとめ

+ +

たぶん、この記事はあなたが遭遇するかもしれない主なアクセシビリティ問題とそれらをどうやってテストして克服するかについての良い下地を与えたでしょう。

+ +

次の記事では、機能の検出について詳しく説明します。

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/JavaScript","Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html new file mode 100644 index 0000000000..98bf8d9394 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html @@ -0,0 +1,620 @@ +--- +title: 自動テストのイントロダクション +slug: Learn/Tools_and_testing/Cross_browser_testing/Automated_testing +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Automated_testing +--- +
 {{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

1日に数回、複数のブラウザやデバイスで手動でテストを実行すると、面倒で時間がかかる場合があります。これを効率的に処理するには、自動化ツールに慣れておく必要があります。この記事では、利用可能なもの、タスクランナーの使い方、そして Sauce Labs や Browser Stack などの市販のブラウザテスト自動化アプリケーションの基本的な使い方を見ていきます。

+ + + + + + + + + + + + +
前提条件:主要な HTMLCSS、および JavaScript 言語に精通していること。クロスブラウザテストの原則の高水準のアイデア。
目標:自動テストにはどのようなものが含まれているのか、それがどのようにあなたの生活を楽にすることができるのか、そして物事を楽にするいくつかの商用製品をどのように利用するかの理解を提供する。
+ +

Automation makes things easy

+ +

Throughout this module we have detailed loads of different ways in which you can test your websites and apps, and explained the sort of scope your cross-browser testing efforts should have in terms of what browsers to test, accessibility considerations, and more. Sounds like a lot of work, doesn't it?

+ +

We agree — testing all the things we've looked at in previous articles manually can be a real pain. Fortunately, there are tools to help us automate some of this pain away. There are two main ways in which we can automate the tests we've been talking about in this module:

+ +
    +
  1. Use a task runner such as Grunt or Gulp, or npm scripts to run tests and clean up code during your build process. This is a great way to perform tasks like linting and minifying code, adding in CSS prefixes or transpiling nascent JavaScript features for maximum cross-browser reach, and so on.
  2. +
  3. Use a browser automation system like Selenium to run specific tests on installed browsers and return results, alerting you to failures in browsers as they crop up. Commercial cross-browser testing apps like Sauce Labs and Browser Stack are based on Selenium, but allow you to access their set up remotely using a simple interface, saving you the hassle of setting up your own testing system.
  4. +
+ +

We will look at how to set up your own Selenium-based testing system in the next article. In this article, we'll look at how to set up a task runner, and use the basic functionality of commercial systems like the ones mentioned above.

+ +
+

Note: the above two categories are not mutually exclusive. It is possible to set up a task runner to access a service like Sauce Labs via an API, run cross browser tests, and return results. We will look at this below as well.

+
+ +

Using a task runner to automate testing tools

+ +

As we said above, you can drastically speed up common tasks such as linting and minifying code by using a task runner to run everything you need to run automatically at a certain point in your build process. For example, this could be every time you save a file, or at some other point. Inside this section we'll look at how to automate task running with Node and Gulp, a beginner-friendly option.

+ +

Setting up Node and npm

+ +

Most tools these days are based on {{Glossary("Node.js")}}, so you'll need to install it from nodejs.org:

+ +
    +
  1. Download the installer for your system from the above site. (If you already have Node and npm installed, jump to point 4)
  2. +
  3. Install it like you would any other program. Note that Node comes with Node Package Manager (npm), which allows you to easily install packages, share your own packages with others, and run useful scripts on your projects.
  4. +
  5. Once the install completes, test that node is installed by typing the following into the terminal, which returns the installed versions of Node and npm: +
    node -v
    +npm -v
    +
  6. +
  7. If you've got Node/npm already installed, you should update them to their latest versions. To update Node, the most reliable way is to download and install an updated installer package from their website (see link above). To update npm, use the following command in your terminal: +
    npm install npm@latest -g
    +
  8. +
+ +
+

Note: If the above command fails with permissions errors, Fixing npm permissions should sort you out.

+
+ +

To start using Node/npm-based packages on your projects, you need to set up your project directories as npm projects. This is easy to do.

+ +

For example, let's first create a test directory to allow us to play without fear of breaking anything.

+ +
    +
  1. Create a new directory somewhere sensible with using your file manager UI, or by navigating to the location you want and running the following command: +
    mkdir node-test
    +
  2. +
  3. To make this directory an npm project, you just need to go inside your test directory and initialize it, with the following: +
    cd node-test
    +npm init
    +
  4. +
  5. This second command will ask you many questions to find out the information required to set up the project; you can just select the defaults for now.
  6. +
  7. Once all the questions have been asked, it will ask you if the information entered is OK. type yes and press Enter/Return and npm will generate a package.json file in your directory.
  8. +
+ +

This file is basically a config file for the project. You can customize it later, but for now it'll look something like this:

+ +
{
+  "name": "node-test",
+  "version": "1.0.0",
+  "description": "Test for npm projects",
+  "main": "index.js",
+  "scripts": {
+    "test": "test"
+  },
+  "author": "Chris Mills",
+  "license": "MIT"
+}
+ +

With this, you are ready to move on.

+ +

Setting up Gulp automation

+ +

Let's look at setting up Gulp and using it to automate some testing tools.

+ +
    +
  1. To begin with, create a test npm project using the procedure detailed at the bottom of the previous section.
  2. +
  3. Next, you'll need some sample HTML, CSS and JavaScript content to test your system on — make copies of our sample index.html, main.js, and style.css files in a subfolder with the name src inside your project folder. You can try your own test content if you like, but bear in mind that such tools won't work on internal JS/CSS — you need external files.
  4. +
  5. First, install gulp globally (meaning, it will be available across all projects) using the following command: +
    npm install --global gulp-cli
    +
  6. +
  7. Next, run the following command inside your npm project directory root to set up gulp as a dependency of your project: +
    npm install --save-dev gulp
    +
  8. +
  9. Now create a new file inside your project directory called gulpfile.js. This is the file that will run all our tasks. Inside this file, put the following: +
    var gulp = require('gulp');
    +
    +gulp.task('default', function() {
    +  console.log('Gulp running');
    +});
    + This requires the gulp module we installed earlier, and then runs a basic task that does nothing except for printing a message to the terminal — this is useful for letting us know that Gulp is working. Each gulp task is written in the same basic format — gulp's task() method is run, and given two parameters — the name of the task, and a callback function containing the actual code to run to complete the task.
  10. +
  11. You can run your gulp task with the following commands — try this now: +
    gulp
    +
    +
  12. +
+ +

Adding some real tasks to Gulp

+ +

To add some real tasks to Gulp, we need to think about what we want to do. A reasonable set of basic functionalities to run on our project is as follows:

+ + + +

See the links above for full instructions on the different gulp packages we are using.

+ +

To use each plugin, you need to first install it via npm, then require any dependencies at the top of the gulpfile.js file, then add your test(s) to the bottom of it, and finally add the name of your task inside the default task.

+ +

Before you go any further, update the default task to this:

+ +
gulp.task('default', [ ]);
+ +

Inside the array goes the names of all the tasks you want Gulp to run, once you run the gulp command on the command line.

+ +

html-tidy

+ +
    +
  1. Install using the following line: +
    npm install --save-dev gulp-htmltidy
    +
    + +
    +

    Note: --save-dev adds the package as a dependency to your project. If you look in your project's package.json file, you'll see an entry for it as, it has been added to the devDependencies property.

    +
    +
  2. +
  3. Add the following dependencies to gulpfile.js: +
    var htmltidy = require('gulp-htmltidy');
    +
  4. +
  5. Add the following test to the bottom of gulpfile.js: +
    gulp.task('html', function() {
    +  return gulp.src('src/index.html')
    +        .pipe(htmltidy())
    +        .pipe(gulp.dest('build'));
    +});
    +
  6. +
  7. Add 'html' as an item inside the array in the default task.
  8. +
+ +

Here we are grabbing our development index.html file — gulp.src() which allows us to grab a source file to do something with.

+ +

We next use the pipe() function to pass that source to another command to do something else with. We can chain as many of these together as we want. We first run htmltidy() on the source, which goes through and fixes errors in our file. The second pipe() function writes the output HTML file to the build directory.

+ +

In the input version of the file, you may have noticed that we put an empty {{htmlelement("p")}} element; htmltidy has removed this by the time the output file has been created.

+ +

Autoprefixer and css-lint

+ +
    +
  1. Install using the following lines: +
    npm install --save-dev gulp-autoprefixer
    +npm install --save-dev gulp-csslint
    +
  2. +
  3. Add the following dependencies to gulpfile.js: +
    var autoprefixer = require('gulp-autoprefixer');
    +var csslint = require('gulp-csslint');
    +
  4. +
  5. Add the following test to the bottom of gulpfile.js: +
    gulp.task('css', function() {
    +    return gulp.src('src/style.css')
    +        .pipe(csslint())
    +        .pipe(csslint.formatter('compact'))
    +        .pipe(autoprefixer({
    +            browsers: ['last 5 versions'],
    +            cascade: false
    +        }))
    +        .pipe(gulp.dest('build'));
    +});
    +
  6. +
  7. Add 'css' as an item inside the array in the default task.
  8. +
+ +

Here we grab our style.css file, run csslint on it (which outputs a list of any errors in your CSS to the terminal), then runs it through autoprefixer to add any prefixes needed to make nascent CSS features run in older browsers. At the end of the pipe chain, we output our modified prefixed CSS to the build directory. Note that this only works if csslint doesn't find any errors — try removing a curly brace from your CSS file and re-running gulp to see what output you get!

+ +

js-hint and babel

+ +
    +
  1. Install using the following lines: +
    npm install --save-dev gulp-babel @babel/preset-env
    +npm install --save-dev @babel/core
    +npm install jshint gulp-jshint --save-dev
    +
    +
  2. +
  3. Add the following dependencies to gulpfile.js: +
    var babel = require('gulp-babel');
    +var jshint = require('gulp-jshint');
    +
    +
  4. +
  5. Add the following test to the bottom of gulpfile.js: +
    gulp.task('js', function() {
    +    return gulp.src('src/main.js')
    +        .pipe(jshint())
    +        .pipe(jshint.reporter('default'))
    +        .pipe(babel({
    +            presets: ['@babel/env']
    +        }))
    +        .pipe(gulp.dest('build'));
    +});
    +
  6. +
  7. Add 'js' as an item inside the array in the default task.
  8. +
+ +

Here we grab our main.js file, run jshint on it and output the results to the terminal using jshint.reporter; we then pass the file to babel, which converts it to old style syntax and outputs the result into the build directory. Our original code included a fat arrow function, which babel has modified into an old style function.

+ +

Further ideas

+ +

Once all this is all set up, you can run the gulp command inside your project directory, and you should get an output like this:

+ +

+ +

You can then try out the files output by your automated tasks by looking at them inside the build directory, and loading build/index.html in your web browser.

+ +

If you get errors, check that you've added all the dependencies and the tests as shown above; also try commenting out the HTML/CSS/JavaScript code sections and then rerunning gulp to see if you can isolate what the problem is.

+ +

Gulp comes with a watch() function that you can use to watch your files and run tests whenever you save a file. For example, try adding the following to the bottom of your gulpfile.js:

+ +
gulp.task('watch', function(){
+  gulp.watch('src/*.html', ['html']);
+  gulp.watch('src/*.css', ['css']);
+  gulp.watch('src/*.js', ['js']);
+});
+ +

Now try entering the gulp watch command into your terminal. Gulp will now watch your directory, and run the appropriate tasks whenever you save a change to an HTML, CSS, or JavaScript file.

+ +
+

Note: The * character is a wildcard character — here we're saying "run these tasks when any files of these types are saved. You could also use wildcards in your main tasks, for example gulp.src('src/*.css') would grab all your CSS files and then run piped tasks on them.

+
+ +
+

Note: One problem with our watch command above is that our CSSLint/Autoprefixer combination throws full-blown errors when a CSS error is encountered, which stops the watch working. You'll have to restart the watch once a CSS error is encountered, or find another way to do this.

+
+ +

There's a lot more you can do with Gulp. The Gulp plugin directory has literally thousands of plugins to search through.

+ +

Other task runners

+ +

There are many other task runners available. We certainly aren't trying to say that Gulp is the best solution out there, but it works for us and it is fairly accessible to beginners. You could also try using other solutions:

+ + + +

Using commercial testing services to speed up browser testing

+ +

Now let's look at commercial 3rd party browser testing services and what they can do for us.

+ +

The basic premise with such applications is that the company that runs each one has a huge server farm that can run many different tests. When you use this service, you provide a URL of the page you want to test along with information, such as what browsers you want it tested in. The app then configures a new VM with the OS and browser you specified, and returns the test results in the form of screenshots, videos, logfiles, text, etc.

+ +

You can then step up a gear, using an API to access functionality programmatically, which means that such apps can be combined with task runners, such as your own local Selenium environments and others, to create automated tests.

+ +
+

Note: There are other commercial browser testing systems available but in this article, we'll focus on Sauce Labs and BrowserStack. We're not saying that these are necessarily the best tools available, but they are good ones that are simple for beginners to get up and running with.

+
+ +

Sauce Labs

+ +

Getting started with Sauce Labs

+ +

Let's get started with a Sauce Labs Trial.

+ +
    +
  1. Create a Sauce Labs trial account.
  2. +
  3. Sign in. This should happen automatically after you verify your e-mail address.
  4. +
+ +

The basics: Manual tests

+ +

The Sauce Labs dashboard has a lot of options available on it. For now, make sure you are on the Manual Tests tab.

+ +
    +
  1. Click Start a new manual session.
  2. +
  3. In the next screen, type in the URL of a page you want to test (use http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box-fixed.html, for example), then choose a browser/OS combination you want to test by using the different buttons and lists. There is a lot of choice, as you'll see!
  4. +
  5. When you click Start session, a loading screen will then appear, which spins up a virtual machine running the combination you chose.
  6. +
  7. When loading has finished, you can then start to remotely test the web site running in the chosen browser.
  8. +
  9. From here you can see the layout as it would look in the browser you are testing, move the mouse around and try clicking buttons, etc. The top menu allows you to: +
      +
    • Stop the session
    • +
    • Give someone else a URL so they can observe the test remotely.
    • +
    • Copy text/notes to a remote clipboard.
    • +
    • Take a screenshot.
    • +
    • Test in full screen mode.
    • +
    +
  10. +
+ +

Once you stop the session, you'll return to the Manual Tests tab, where you'll see an entry for each of the previous manual sessions you started. Clicking on one of these entries shows more data for the session. In here you can download any screenshots you took , watch a video of the session, and view data logs for the session for example.

+ +
+

Note: This is already very useful, and way more convenient than having to set up all these emulators and virtual machines by yourself.

+
+ +

Advanced: The Sauce Labs API

+ +

Sauce Labs has a restful API that allows you to programmatically retrieve details of your account and existing tests, and annotate tests with further details, such as their pass/fail state which isn't recordable by manual testing alone. For example, you might want to run one of your own Selenium tests remotely using Sauce Labs, to test a certain browser/OS combination, and then pass the test results back to Sauce Labs.

+ +

It has several clients available to allow you to make calls to the API using your favourite environment, be it PHP, Java, Node.js, etc.

+ +

Let's have a brief look at how we'd access the API using Node.js and node-saucelabs.

+ +
    +
  1. First, set up a new npm project to test this out, as detailed in {{anch("Setting up Node and npm")}}. Use a different directory name than before, like sauce-test for example.
  2. +
  3. Install the Node Sauce Labs wrapper using the following command: +
    npm install saucelabs
    +
  4. +
  5. Create a new file inside your project root called call_sauce.js. give it the following contents: +
    var SauceLabs = require('saucelabs');
    +
    +var myAccount = new SauceLabs({
    +  username: "your-sauce-username",
    +  password: "your-sauce-api-key"
    +});
    +
    +myAccount.getAccountDetails(function (err, res) {
    +  console.log(res);
    +  myAccount.getServiceStatus(function (err, res) {
    +    // Status of the Sauce Labs services
    +    console.log(res);
    +    myAccount.getJobs(function (err, jobs) {
    +      // Get a list of all your jobs
    +      for (var k in jobs) {
    +        if ( jobs.hasOwnProperty( k )) {
    +          myAccount.showJob(jobs[k].id, function (err, res) {
    +            var str = res.id + ": Status: " + res.status;
    +            if (res.error) {
    +              str += "\033[31m Error: " + res.error + " \033[0m";
    +            }
    +            console.log(str);
    +          });
    +        }
    +      }
    +    });
    +  });
    +});
    +
  6. +
  7. You'll need to fill in your Sauce Labs username and API key in the indicated places. These can be retrieved from your User Settings page. Fill these in now.
  8. +
  9. Make sure everything is saved, and run your file like so: +
    node call_sauce
    +
  10. +
+ +

Advanced: Automated tests

+ +

We'll cover actually running automated Sauce Lab tests in the next article.

+ +

BrowserStack

+ +

Getting started with BrowserStack

+ +

Let's get started with a BrowserStack Trial.

+ +
    +
  1. Create a BrowserStack trial account.
  2. +
  3. Sign in. This should happen automatically after you verify your e-mail address.
  4. +
  5. When you first sign in, you should be on the Live testing page; if not, click the Live link in the top nav menu.
  6. +
  7. If you are on Firefox or Chrome, you'll be prompted to Install a browser extension in a dialog titled "Enable Local Testing" — click the Install button to proceed. If you are on other browsers you'll still be able to use some of the features (generally via Flash), but you won't get the full experience.
  8. +
+ +

The basics: Manual tests

+ +

The BrowserStack Live dashboard allows you to choose what device and browser you want to test on — Platforms in the left column, devices on the right. When you mouse over or click on each device, you get a choice of browsers available on that device.

+ +

+ +

Clicking on one of those browser icons will load up your choice of platform/device/browser — choose one now, and give it a try.

+ +

+ +
+

Note: The blue device icon next to some of the mobile device choices signals that you will be testing on a real device; choices without that icon will be run on an emulator.

+
+ +

You'll find that you can enter URLs into the address bar, and use the other controls like you'd expect on a real device. You can even do things like copy and paste from the device to your clipboard, scroll up and down by dragging with the mouse, or use appropriate gestures (e.g. pinch/zoom, two fingers to scroll) on the touchpads of supporting devices (e.g. Macbook). Note that not all features are available on all devices.

+ +

You'll also see a menu that allows you to control the session.

+ +

+ +

The features here are as follows:

+ + + +
+

Note: This is already very useful, and way more convenient than having to set up all these emulators and virtual machines by yourself.

+
+ +

Other basic features

+ +

If you go back to the main BrowserStack page, you'll find a couple of other useful basic features under the More menu option:

+ + + +

Advanced: The BrowserStack API

+ +

BrowserStack also has a restful API that allows you to programmatically retrieve details of your account plan, sessions, builds, etc.

+ +

It has several clients available to allow you to make calls to the API using your favourite environment, be it PHP, Java, Node.js, etc.

+ +

Let's have a brief look at how we'd access the API using Node.js.

+ +
    +
  1. First, set up a new npm project to test this out, as detailed in {{anch("Setting up Node and npm")}}. Use a different directory name than before, like bstack-test for example.
  2. +
  3. Create a new file inside your project root called call_bstack.js. give it the following contents: +
    var request = require("request");
    +
    +var bsUser = "BROWSERSTACK_USERNAME";
    +var bsKey = "BROWSERSTACK_ACCESS_KEY";
    +var baseUrl = "https://" + bsUser + ":" + bsKey + "@www.browserstack.com/automate/";
    +
    +function getPlanDetails(){
    +    request({uri: baseUrl + "plan.json"}, function(err, res, body){
    +        console.log(JSON.parse(body));
    +    });
    +    /* Response:
    +    {
    +        automate_plan: <string>,
    +        parallel_sessions_running: <int>,
    +        team_parallel_sessions_max_allowed: <int>,
    +        parallel_sessions_max_allowed: <int>,
    +        queued_sessions: <int>,
    +        queued_sessions_max_allowed: <int>
    +    }
    +    */
    +}
    +
    +getPlanDetails();
    +
    +
  4. +
  5. You'll need to fill in your BrowserStack username and API key in the indicated places. These can be retrieved from your BrowserStack automation dashboard. Fill these in now.
  6. +
  7. Make sure everything is saved, and run your file like so: +
    node call_bstack
    +
  8. +
+ +

Below we've also provided some other ready-made functions you might find useful when working with the BrowserStack restful API.

+ +
function getBuilds(){
+	request({uri: baseUrl + "builds.json"}, function(err, res, body){
+		console.log(JSON.parse(body));
+	});
+	/* Response:
+	[
+		{
+			automation_build: {
+				name: <string>,
+				duration: <int>,
+				status: <string>,
+				hashed_id: <string>
+			}
+		},
+		{
+			automation_build: {
+				name: <string>,
+				duration: <int>,
+				status: <string>,
+				hashed_id: <string>
+			}
+		},
+		...
+	]
+	*/
+};
+
+function getSessionsInBuild(build){
+	var buildId = build.automation_build.hashed_id;
+	request({uri: baseUrl + "builds/" + buildId + "/sessions.json"}, function(err, res, body){
+		console.log(JSON.parse(body));
+	});
+	/* Response:
+	[
+		{
+			automation_session: {
+				name: <string>,
+				duration: <int>,
+				os: <string>,
+				os_version: <string>,
+				browser_version: <string>,
+				browser: <string>,
+				device: <string>,
+				status: <string>,
+				hashed_id: <string>,
+				reason: <string>,
+				build_name: <string>,
+				project_name: <string>,
+				logs: <string>,
+				browser_url: <string>,
+				public_url: <string>,
+				video_url: <string>,
+				browser_console_logs_url: <string>,
+				har_logs_url: <string>
+			}
+		},
+		{
+			automation_session: {
+				name: <string>,
+				duration: <int>,
+				os: <string>,
+				os_version: <string>,
+				browser_version: <string>,
+				browser: <string>,
+				device: <string>,
+				status: <string>,
+				hashed_id: <string>,
+				reason: <string>,
+				build_name: <string>,
+				project_name: <string>,
+				logs: <string>,
+				browser_url: <string>,
+				public_url: <string>,
+				video_url: <string>,
+				browser_console_logs_url: <string>,
+				har_logs_url: <string>
+			}
+		},
+		...
+	]
+	*/
+}
+
+function getSessionDetails(session){
+	var sessionId = session.automation_session.hashed_id;
+	request({uri: baseUrl + "sessions/" + sessionId + ".json"}, function(err, res, body){
+		console.log(JSON.parse(body));
+	});
+	/* Response:
+	{
+		automation_session: {
+			name: <string>,
+			duration: <int>,
+			os: <string>,
+			os_version: <string>,
+			browser_version: <string>,
+			browser: <string>,
+			device: <string>,
+			status: <string>,
+			hashed_id: <string>,
+			reason: <string>,
+			build_name: <string>,
+			project_name: <string>,
+			logs: <string>,
+			browser_url: <string>,
+			public_url: <string>,
+			video_url: <string>,
+			browser_console_logs_url: <string>,
+			har_logs_url: <string>
+		}
+	}
+	*/
+}
+ +

Advanced: Automated tests

+ +

We'll cover actually running automated BrowserStack tests in the next article.

+ +

Summary

+ +

This was quite a ride, but I'm sure you can start to see the benefit in having automation tools do a lot of the heavy lifting for you in terms of testing.

+ +

In the next article, we'll look at setting up our own local automation system using Selenium, and how to combine that with services such as Sauce Labs and BrowserStack

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html new file mode 100644 index 0000000000..1de223efa2 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html @@ -0,0 +1,357 @@ +--- +title: 機能検出の実装 +slug: Learn/Tools_and_testing/Cross_browser_testing/Feature_detection +tags: + - Article + - Beginner + - CSS + - CodingScripting + - JavaScript + - Learn + - Modernizr + - Testing + - Tools + - cross browser + - feature detection + - 機能検出 +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Feature_detection +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Accessibility","Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

機能検出は、あるブラウザーがあるコードのブロックに対応しているかどうかを調べ、対応しているか (またはしていないか) に応じて異なるコードを実行することで、ブラウザーが常に動作し、ブラウザーによってクラッシュやエラーが発生しないようにします。この記事では、独自の単純な機能検出の書き方、実装をスピードアップするためのライブラリの使い方、 @supports などの機能検出のためのネイティブ機能について詳しく説明します。

+ + + + + + + + + + + + +
前提条件:主要な HTMLCSS、および JavaScript 言語に精通していること。クロスブラウザテストの原則の高水準のアイデア。
目標:機能検出の概念について理解し、CSS と JavaScript で適切な解決方法を実装できるようにする。
+ +

機能検出の概念

+ +

機能検出の根底にあるアイデアは、プログラムを実行中のブラウザーがある特定の機能に対応しているかを確かめ、その結果に応じて異なるコードを実行するということで、対応ブラウザーと非対応ブラウザーのいずれでも許容できる挙動となるようにすることです。もしこの対策をしなければ、その特定の機能に対応していないブラウザーではあなたのサイトが正常に表示されなかったり、エラーを起こしてユーザーの体験を悪化させるでしょう。

+ +

それでは、私たちが Handling common JavaScript problems で触れた例を振り返ってみましょう。Geolocation API (ブラウザーを実行している端末の位置情報を返します)は、 Navigator オブジェクトに含まれる geolocation プロパティを主なエントリーポイントとして持っています。そこで、以下のようにしてブラウザーが位置情報機能に対応しているかどうかを検出できます。

+ +
if ("geolocation" in navigator) {
+  navigator.geolocation.getCurrentPosition(function(position) {
+    // Google Maps API を用いて現在位置をマップ上に表示します
+  });
+} else {
+  // 位置情報がなくてもマップを表示できるようにします
+}
+ +

しかし、機能検出のためのコードを毎回自分で書くよりも、確立された既存の機能検出ライブラリを使うほうが良いでしょう。この用途では Modernizr が一般に利用されています。Modernizr には後ほど触れます。

+ +

次に進む前にもう1つお伝えさせてください。機能検出とブラウザー検出(サイトにアクセスしているブラウザーの種類の検出)を混同しないでください。これはいかなる場合にも避けられるべき悪しき風習です。詳しくは Using bad browser sniffing code を参照してください。

+ +

Writing your own feature detection tests

+ +

In this section, we'll look at implementing your own feature detection tests, in both CSS and JavaScript.

+ +

CSS

+ +

You can write tests for CSS features by testing for the existence of element.style.property (e.g. paragraph.style.transform) in JavaScript.

+ +

A classic example might be to test for Flexbox support in a browser; for browsers that support the newest Flexbox spec, we could use a flexible and robust flex layout. For browsers that don't, we could use a floated layout that works OK, although it is slightly more brittle and hacky, and not as cool-looking.

+ +

Let's implement something that demonstrates this, although we'll keep it simple for now.

+ +
    +
  1. Start by making local copies of our css-feature-detect.html, flex-layout.css, float-layout-css, and basic-styling.css files. Save them in a new directory.
  2. +
  3. We will add the HTML5 Shiv to our example too so that the HTML5 semantic elements will style properly in older versions of IE. Download the latest version (see Manual installation), unzip the ZIP file, copy the html5shiv-printshiv.min.js and html5shiv.min.js files into your example directory, and link to one of the files by putting the following under your {{htmlelement("title")}} element: +
    <script src="html5shiv.min.js"></script>
    +
  4. +
  5. Have a look at your example CSS files — you'll see that basic-styling.css handles all the styling that we want to give to every browser, whereas the other two CSS files contain the CSS we want to selectively apply to browser depending on their support levels. You can look at the different effects these two files they have by manually changing the CSS file referred to by the second {{htmlelement("link")}} element, but let's instead implement some JavaScript to automatically swap them as needed.
  6. +
  7. First, remove the contents of the second <link> element's href attribute. We will fill this in dynamically later on.
  8. +
  9. Next, add a <script></script> element at the bottom of your body (just before the closing </body> tag).
  10. +
  11. Give it the following contents: +
    const conditional = document.querySelector('.conditional');
    +const testElem = document.createElement('div');
    +if (testElem.style.flex !== undefined && testElem.style.flexFlow !== undefined) {
    +  conditional.setAttribute('href', 'flex-layout.css');
    +} else {
    +  conditional.setAttribute('href', 'float-layout.css');
    +}
    +
  12. +
+ +

Here we are grabbing a reference to the second <link> element, and creating a <div> element as part of our test. In our conditional statement, we test that the {{cssxref("flex")}} and {{cssxref("flex-flow")}} properties exist in the browser. Note how the JavaScript representations of those properties that are stored inside the {{domxref("HTMLElement.style")}} object use lower camel case, not hyphens, to separate the words.

+ +
+

Note: If you have trouble getting this to work, you can compare it to our css-feature-detect-finished.html code (see also the live version).

+
+ +

When you save everything and try out your example, you should see the flexbox layout applied to the page if the browser supports modern flexbox, and the float layout if not.

+ +
+

Note: Often such an approach is overkill for a minor feature detection problem — you can often get away with using multiple vendor prefixes and fallback properties, as described in CSS fallback behavior and Handling CSS prefixes.

+
+ +

@supports

+ +

In recent times, CSS has had its own native feature detection mechanism introduced — the {{cssxref("@supports")}} at-rule. This works in a similar manner to media queries (see also Responsive design problems) — except that instead of selectively applying CSS depending on a media feature like a resolution, screen width or aspect ratio, it selectively applies CSS depending on whether a CSS feature is supported.

+ +

For example, we could rewrite our previous example to use @supports — see supports-feature-detect.html and supports-styling.css. If you look at the latter, you'll see a couple of @supports blocks, for example:

+ +
@supports (flex-flow: row) and (flex: 1) {
+
+  main {
+    display: flex;
+  }
+
+  main div {
+    padding-right: 4%;
+    flex: 1;
+  }
+
+  main div:last-child {
+    padding-right: 0;
+  }
+
+}
+ +

This at-rule block applies the CSS rule within only if the current browser supports both the flex-flow: row and flex: 1 declarations. For each condition to work, you need to include a complete declaration (not just a property name) and NOT include the semi-colon on the end.

+ +

@supports also has OR and NOT logic available — the other block applies the float layout if the flexbox properties are not available:

+ +
@supports not (flex-flow: row) and (flex: 1) {
+
+  /* rules in here */
+
+}
+ +

This may look a lot more convenient than the previous example — we can do all of our feature detection in CSS, no JavaScript required, and we can handle all the logic in a single CSS file, cutting down on HTTP requests. the problem here is browser support — @supports is not supported at all in IE, and only supported in very recent versions of Safari/iOS WebKit (9+/9.2+), whereas the JavaScript version should work in much older browsers (probably back to IE8 or 9, although older versions of IE will have additional problems, such as not supporting {{domxref("Document.querySelector")}}, and having a messed up box model).

+ +

JavaScript

+ +

We already saw an example of a JavaScript feature detection test earlier on. Generally, such tests are done via one of the following common patterns:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Summary of JavaScript feature detection techniques
Feature detection typeExplanationExample
If member in objectCheck whether a certain method or property (typically an entry point into using the API or other feature you are detecting for) exists in its parent Object. +

if("geolocation" in navigator) { ... }

+
Property on elementCreate an element in memory using {{domxref("Document.createElement()")}} and then check if a property exists on it. The example shown is a way of detecting HTML5 Canvas support.function supports_canvas() {
+ return !!document.createElement('canvas').getContext;
+ }
+
+ if(supports_canvas()) { ... }
Method on element return valueCreate an element in memory using {{domxref("Document.createElement()")}} and then check if a method exists on it. If it does, check what value it returns.See Dive Into HTML5 Video Formats detection test.
Property on element retains valueCreate an element in memory using {{domxref("Document.createElement()")}}, set a property to a certain value, then check to see if the value is retained.See Dive into HTML5 <input> types detection test.
+ +
+

Note: The double NOT in the above example (!!) is a way to force a return value to become a "proper" boolean value, rather than a {{glossary("Truthy")}}/{{glossary("Falsy")}} value that may skew the results.

+
+ +

The Dive into HTML5 Detecting HTML5 Features page has a lot more useful feature detection tests besides the ones listed above, and you can generally find a feature detection test for most things by searching for "detect support for YOUR-FEATURE-HERE" in your favorite search engine. Bear in mind though that some features, however, are known to be undetectable — see Modernizr's list of Undetectables.

+ +

matchMedia

+ +

We also wanted to mention the {{domxref("Window.matchMedia")}} JavaScript feature at this point too. This is a property that allows you to run media query tests inside JavaScript. It looks like this:

+ +
if (window.matchMedia("(max-width: 480px)").matches) {
+  // run JavaScript in here.
+}
+ +

As an example, our Snapshot demo makes use of it to selectively apply the Brick JavaScript library and use it to handle the UI layout, but only for the small screen layout (480px wide or less). We first use the media attribute to only apply the Brick CSS to the page if the page width is 480px or less:

+ +
<link href="dist/brick.css" type="text/css" rel="stylesheet" media="all and (max-width: 480px)">
+ +

We then use matchMedia() in the JavaScript several times, to only run Brick navigation functions if we are on the small screen layout (in wider screen layouts, everything can be seen at once, so we don't need to navigate between different views).

+ +
if (window.matchMedia("(max-width: 480px)").matches) {
+  deck.shuffleTo(1);
+}
+ +

Using Modernizr to implement feature detection

+ +

It is possible to implement your own feature detection tests using techniques like the ones detailed above. You might as well use a dedicated feature detection library however, as it makes things much easier. The mother of all feature detection libraries is Modernizr, and it can detect just about everything you'll ever need. Let's look at how to use it now.

+ +

When you are experimenting with Modernizr you might as well use the development build, which includes every possible feature detection test. Download this now by:

+ +
    +
  1. Clicking on the Development build link.
  2. +
  3. Clicking the big pink Build button on the page that comes up.
  4. +
  5. Clicking the top Download link in the dialog box that appears.
  6. +
+ +

Save it somewhere sensible, like the directory you've been creating your other examples for in this article.

+ +

When you are using Modernizr in production, you can go to the Download page you've already visited and click the plus buttons for only the features you need feature detects for. Then when you click the Build button, you'll download a custom build containing only those feature detects, making for a much smaller file size.

+ +

CSS

+ +

Let's have a look at how Modernizr works in terms of selectively applying CSS.

+ +
    +
  1. First, make a copy of supports-feature-detect.html and supports-styling.css. Save them as modernizr-css.html and modernizr-css.css.
  2. +
  3. Update your {{htmlelement("link")}} element in your HTML so it points to the correct CSS file (you should also update your {{htmlelement("title")}} element to something more suitable!): +
    <link href="modernizr-css.css" rel="stylesheet">
    +
  4. +
  5. Above this <link> element, add a {{htmlelement("script")}} element to apply the Modernizr library to the page, as shown below. This needs to be applied to the page before any CSS (or JavaScript) that might make use of it. +
    <script src="modernizr-custom.js"></script>
    +
  6. +
  7. Now edit your opening <html> tag, so that it looks like this: +
    <html class="no-js">
    +
  8. +
+ +

At this point, try loading your page, and you'll get an idea of how Modernizr works for CSS features. If you look at the DOM inspector of your browser's developer tools, you'll see that Modernizr has updated your <html> class value like so:

+ +
<html class="js no-htmlimports sizes flash transferables applicationcache blobconstructor
+blob-constructor cookies cors ...AND LOADS MORE VALUES!>
+ +

It now contains a large number of classes that indicate the support status of different technology features. As an example, if the browser didn't support flexbox at all, <html> would be given a class name of no-flexbox. If it did support modern flexbox, it would get a class name of flexbox. If you search through the class list, you'll also see others relating to flexbox, like:

+ + + +
+

Note: You can find a list of what all the class names mean — see Features detected by Modernizr.

+
+ +

Moving on, let's update our CSS to use Modernizr rather than @supports. Go into modernizr-css.css, and replace the two @supports blocks with the following:

+ +
/* Properties for browsers with modern flexbox */
+
+.flexbox main {
+  display: flex;
+}
+
+.flexbox main div {
+  padding-right: 4%;
+  flex: 1;
+}
+
+.flexbox main div:last-child {
+  padding-right: 0;
+}
+
+/* Fallbacks for browsers that don't support modern flexbox */
+
+.no-flexbox main div {
+  width: 22%;
+  float: left;
+  padding-right: 4%;
+}
+
+.no-flexbox main div:last-child {
+  padding-right: 0;
+}
+
+.no-flexbox footer {
+  clear: left;
+}
+ +

So how does this work? Because all those class names have been put on the <html> element, you can target browsers that do or don't support a feature using specific descendant selectors. So here we're applying the top set of rules only to browsers that do support flexbox, and the bottom set of rules only to browsers that don't (no-flexbox).

+ +
+

Note: Bear in mind that all of Modernizr's HTML and JavaScript feature tests are also reported in these class names, so you can quite happily apply CSS selectively based on whether the browser supports HTML or JavaScript features, if needed.

+
+ +
+

Note: If you have trouble getting this to work, check your code against our modernizr-css.html and modernizr-css.css files (see this running live also).

+
+ +

JavaScript

+ +

Modernizr is also equally well-prepared for implementing JavaScript feature detects too. It does this by making the global Modernizr object available to the page it is applied to, which contains results of the feature detects as true/false properties.

+ +

For example, load up our modernizr-css.html example in your browser, then try going to your JavaScript console and typing in Modernizr. followed by some of those class names (they are the same here too). For example:

+ +
Modernizr.flexbox
+Modernizr.websqldatabase
+Modernizr.xhr2
+Modernizr.fetch
+ +

The console will return true/false values to indicate whether your browser supports those features or not.

+ +

Let's look at an example to show how you'd use those properties.

+ +
    +
  1. First of all, make a local copy of the modernizr-js.html example file.
  2. +
  3. Attach the Modernizr library to the HTML using a <script> element, as we have done in previous demos. Put it above the existing <script> element, which is attaching the Google Maps API to the page.
  4. +
  5. Next, fill in the YOUR-API-KEY placeholder text in the second <script> element (as it is now) with a valid Google Maps API key. To get a key, sign in to a Google account, go to the Get a Key/Authentication page, then click the blue Get a Key button and follow the instructions.
  6. +
  7. Finally, add another <script> element at the bottom of the HTML body (just before the </body> tag), and put the following script inside the tags: +
    if (Modernizr.geolocation) {
    +
    +  navigator.geolocation.getCurrentPosition(function(position) {
    +
    +    let latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
    +    let myOptions = {
    +      zoom: 8,
    +      center: latlng,
    +      mapTypeId: google.maps.MapTypeId.TERRAIN,
    +      disableDefaultUI: true
    +    }
    +    let map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    +  });
    +
    +} else {
    +  const para = document.createElement('p');
    +  para.textContent = 'Argh, no geolocation!';
    +  document.body.appendChild(para);
    +}
    +
  8. +
+ +

Try your example out! Here we use the Modernizr.geolocation test to check whether geolocation is supported by the current browser. If it is, we run some code that gets your device's current location, and plots it on a Google Map.

+ +

Summary

+ +

This article covered feature detection in a reasonable amount of detail, going through the main concepts and showing you how to both implement your own feature detection tests and use the Modernizr library to implement tests more easily.

+ +

Next up, we'll start looking at automated testing.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Accessibility","Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

In this module

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html new file mode 100644 index 0000000000..62e21f35a2 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html @@ -0,0 +1,508 @@ +--- +title: 一般的な HTML と CSS の問題への対処 +slug: Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS +tags: + - CSS + - CodingScripting + - HTML + - linting + - クロスブラウザ + - セレクタ + - テスト + - 初心者 + - 学習 + - 記事 +translation_of: Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies","Learn/Tools_and_testing/Cross_browser_testing/JavaScript", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

ここでは、HTML と CSS のコードで発生する可能性のある一般的なクロスブラウザの問題、および問題の発生を防ぐため、または発生する問題を修正するために使用できるツールについて具体的に説明します。これには、コードのリンティング、CSS プレフィックスの処理、問題を追跡するためのブラウザの開発者ツールの使用、ブラウザにサポートを追加するための polyfill の使用、レスポンシブデザイン問題への取り組みなどが含まれます。

+ + + + + + + + + + + + +
前提条件:主要な HTMLCSS、および JavaScript 言語に精通していること。クロスブラウザテストの原則の高水準のアイデア。
目標:一般的な HTML と CSS のクロスブラウザの問題を診断し、それらを修正するための適切なツールとテクニックを使うことができるようにする。
+ +

HTML と CSS の問題

+ +

一部の HTML と CSS の問題は、両方の言語がかなり単純で、コードがうまく作成され、効率的であり、ページ上に「機能の目的」を意味的に記述していることを確認するという意味で開発者がそれらについて真剣に考えていないという事実にあります。最悪の場合、JavaScript を使用して Web ページのコンテンツとスタイル全体を生成するため、ページにアクセスできなくなり、パフォーマンスが低下します (DOM 要素の生成にはコストがかかります)。他のケースでは、初期の機能がブラウザ間で一貫してサポートされていないため、一部の機能やスタイルが一部のユーザには機能しないことがあります。
+ レスポンシブデザインの問題も一般的です。デスクトップブラウザで見栄えの良いサイトはモバイル端末だとひどい経験を提供するかもしれません、内容が読むには小さすぎるか、高精細なアニメーションのせいで遅いでしょう。

+ +

HTML/CSS に起因するクロスブラウザエラーを減らす方法を見てみましょう。

+ +

まず最初に:一般的な問題を解決する

+ +

このシリーズの最初の記事では、まずクロスブラウザの問題に集中する前に、デスクトップ/モバイルの最新ブラウザでいくつかテストしてコードが正常に機能するか確認することをお勧めします。

+ +

HTML のデバッグおよび CSS のデバッグの記事では、HTML/CSS のデバッグに関する基本的なガイダンスをいくつか提供しました。基本に慣れていない場合は、先に進む前に必ずこれらの記事をよく読んでください。

+ +

基本的には、HTML と CSS のコードが整形式で、構文エラーがないかどうかをチェックすることです。

+ +
+

メモ: CSS と HTML に関する一般的な問題の1つは、異なる CSS ルールが互いに矛盾が生じるときに発生します。 サードパーティのコードを使用している場合、これは特に問題になる可能性があります。たとえば、CSS フレームワークを使用して、それが使用しているクラス名の1つが別の目的ですでに使用されているものと衝突しているとします。 または、ある種のサードパーティ API (たとえば広告バナーの生成) によって生成された HTML に、すでに別の目的で使用されているクラス名または ID が含まれていることもあります。これが起こらないようにするには、最初に使用しているツールを調べて、それらを中心にコードを設計する必要があります。また、"名前空間"  CSS も価値があります。ウィジェットがある場合は、それが明確なクラスを持っていることを確認してから、このクラスでウィジェット内の要素を選択するセレクタを起動します。そうすれば競合は起こりにくくなります。例えば、 .audio-player ul a です。

+
+ +

検証

+ +

HTML の検証では、すべてのタグが適切に閉じられてネストされていること、DOCTYPE を使用していること、およびタグを正しい目的で使用していることを確認します。良い戦略はコードを定期的に検証することです。これを可能にするサービスの 1 つに、W3C マークアップ検証サービスがあります。これを使用すると、コードを指定してエラーのリストを返すことができます。

+ +

The HTML validator homepage

+ +

CSS にも同様の話があります — プロパティ名が正しくつづられていること、プロパティ値が正しくつづられていて、それらが使われているプロパティに対して有効であること、中括弧を見逃していないということです。この目的のために、W3C には CSS Validator も用意されています。

+ +

Linters

+ +

取りうるもう一つの良い選択肢は、エラーを指摘するだけでなく、CSS の悪いプラクティスについての警告、および他の点にもフラグを立てることができる、いわゆる Linter アプリケーションです。Linter は一般的に、エラー/警告の報告においてより厳格またはより緩やかになるようにカスタマイズできます。

+ +

オンラインリンターアプリケーションは多数ありますが、そのうち最良のものはおそらく Dirty Markup (HTML、CSS、JavaScript)、および CSS Lint (CSS のみ) です。これらはコードをウィンドウに貼り付けることができ、十字でどんなエラーにでもフラグを立てるでしょう、そしてそれは問題が何であるかを知らせるエラーメッセージを得るためにそれから隠されることができます。Dirty Markup では、Clean ボタンを使用してマークアップを修正することもできます。

+ +

+ +

However, it is not very convenient to have to copy and paste your code over to a web page to check its validity several times. What you really want is a linter that will fit into your standard workflow with the minimum of hassle.

+ +

Many code editors have linter plugins. Github's Atom code editor for example has a rich plugin ecosystem available, with many linting options. To show you an example of how such plugins generally work:

+ +
    +
  1. Install Atom (if you haven't got an up-to-date version already installed) — download it from the Atom page linked above.
  2. +
  3. Go to Atom's Preferences... dialog (e.g. by Choosing Atom > Preferences... on Mac, or File > Preferences... on Windows/Linux) and choose the Install option in the left hand menu.
  4. +
  5. In the Search packages text field, type "lint" and press Enter/Return to search for linting-related packages.
  6. +
  7. You should see a package called lint at the top of the list. Install this first (using the Install button), as other linters rely on it to work. After that, install the linter-csslint plugin for linting CSS, and the linter-tidy plugin for linting HTML.
  8. +
  9. After the packages have finished installing, try loading up an HTML file and a CSS file: you'll see any issues highlighted with green (for warnings) and red (for errors) circles next to the line numbers, and a separate panel at the bottom provides line numbers, error messages, and sometimes suggested values or other fixes.
  10. +
+ +

+ +

Other popular editors have similar linting packages available. For example, see:

+ + + +

Browser developer tools

+ +

The developer tools built into most browsers also feature useful tools for hunting down errors, mainly for CSS.

+ +
+

メモ: ブラウザが不正な形式のマークアップを自動的に修正しようとするため、HTML エラーは開発ツールではそれほど簡単には表示されない傾向があります。W3C バリデータは HTML エラーを取得するための最良の方法です — 上の {{anch("Validation")}} を見てください。

+
+ +

As an example, in Firefox the CSS inspector will show CSS declarations that aren't applied crossed out, with a warning triangle. Hovering the warning triangle will provide a descriptive error message:

+ +

+ +

Other browser devtools have similar features.

+ +

Common cross browser problems

+ +

Now let's move on to look at some of the most common cross browser HTML and CSS problems. The main areas we'll look at are lack of support for modern features, and layout issues.

+ +

Older browsers not supporting modern features

+ +

This is a common problem, especially when you need to support old browsers (such as old IE versions) or you are using features that are implemented using CSS prefixes. In general, most core HTML and CSS functionality (such as basic HTML elements, CSS basic colors and text styling) works across most browsers you'll want to support; more problems are uncovered when you start wanting to use newer features such as Flexbox, or HTML5 video/audio, or even more nascent, CSS Grids or -webkit-background-clip: text.

+ +

Once you've identified a list of potential problem technologies you will be using, it is a good idea to research what browsers they are supported in, and what related techniques are useful. See {{anch("Finding help")}} below.

+ +

HTML fallback behaviour

+ +

Some problems can be solved by just taking advantage of the natural way in which HTML/CSS work.

+ +

Unrecognised HTML elements are treated by the browser as anonymous inline elements (effectively inline elements with no semantic value, similar to {{htmlelement("span")}} elements). You can still refer to them by their names, and style them with CSS, for example — you just need to make sure they are behaving as you want them to, for example setting display: block; on all of the new semantic elements (such as {{htmlelement("article")}}, {{htmlelement("aside")}}, etc.), but only in old versions of IE that don't recognise them (so, IE 8 and lower). This way new browsers can just use the code as normal, but older IE versions will be able to style these elements too.

+ +
+

Note: See {{anch("IE conditional comments")}} for the best way to do this.

+
+ +

More complex elements like HTML <video>, <audio>, and <canvas> (and other features besides) have natural mechanisms for fallbacks to be added, which work on the same principle as described above. You can add fallback content in between the opening and closing tags, and non-supporting browsers will effectively ignore the outer element and run the nested content.

+ +

For example:

+ +
<video id="video" controls preload="metadata" poster="img/poster.jpg">
+  <source src="video/tears-of-steel-battle-clip-medium.mp4" type="video/mp4">
+  <source src="video/tears-of-steel-battle-clip-medium.webm" type="video/webm">
+  <source src="video/tears-of-steel-battle-clip-medium.ogg" type="video/ogg">
+  <!-- Flash fallback -->
+  <object type="application/x-shockwave-flash" data="flash-player.swf?videoUrl=video/tears-of-steel-battle-clip-medium.mp4" width="1024" height="576">
+     <param name="movie" value="flash-player.swf?videoUrl=video/tears-of-steel-battle-clip-medium.mp4" />
+     <param name="allowfullscreen" value="true" />
+     <param name="wmode" value="transparent" />
+     <param name="flashvars" value="controlbar=over&amp;image=img/poster.jpg&amp;file=flash-player.swf?videoUrl=video/tears-of-steel-battle-clip-medium.mp4" />
+      <img alt="Tears of Steel poster image" src="img/poster.jpg" width="1024" height="428" title="No video playback possible, please download the video from the link below" />
+  </object>
+  <!-- Offer download -->
+  <a href="video/tears-of-steel-battle-clip-medium.mp4">Download MP4</a>
+</video>
+ +

This example (taken from Creating a cross-browser video player) includes not only a Flash video fallback for older IE versions, but also a simple link allowing you to download the video if even the Flash player doesn't work, so at least the user can still access the video.

+ +
+

Note: 3rd party libraries like Video.js and JW Player use such fallback mechanisms to provide cross-browser support.

+
+ +

HTML5 form elements also exhibit fallback qualities — HTML5 introduced some special <input> types for inputting specific information into forms, such as times, dates, colors, numbers, etc. These are very useful, particularly on mobile platforms, where providing a pain-free way of entering data is very important for the user experience. Supporting platforms provide special UI widgets when these input types are used, such as a calendar widget for entering dates.

+ +

The following example shows date and time inputs:

+ +
<form>
+  <div>
+    <label for="date">Enter a date:</label>
+    <input id="date" type="date">
+  </div>
+  <div>
+    <label for="time">Enter a time:</label>
+    <input id="time" type="time">
+  </div>
+</form>
+ +

The output of this code is as follows:

+ + + +

 

+ +
<form>
+      <div>
+        <label for="date">Enter a date:</label>
+        <input id="date" type="date">
+      </div>
+      <div>
+        <label for="time">Enter a time:</label>
+        <input id="time" type="time">
+      </div>
+    </form>
+ + + +

{{ EmbedLiveSample('Hidden_example', '100%', 150) }}

+ +
+

Note: You can also see this running live as forms-test.html on GitHub (see the source code also).

+
+ +

If you view the example on a supporting browser like desktop/Android Chrome or iOS Safari, you'll see the special widgets/features in action as you try to input data. On a non-supporting platform such as Firefox or Internet Explorer, the inputs will just fallback to normal text inputs, so at least the user can still enter some information.

+ +

Note: Of course, this may not be a great solution for your project's needs — the difference in visual presentation is not great, plus it is harder to guarantee the data will be entered in the format you want it in. For cross browser forms, It is probably better to rely on simple form elements, or selectively using advanced form elements only in supporting browsers, or using a library that provides decent cross browser form widgets, such as jQuery UI or Bootstrap datepicker.

+ +

CSS fallback behaviour

+ +

CSS is arguably better at fallbacks than HTML. If a browser encounters a declaration or rule it doesn't understand, it just skips it completely without applying it or throwing an error. This might be frustrating for you and your users if such a mistake slips through to production code, but at least it means the whole site doesn't come crashing down because of one error, and if used cleverly you can use it to your advantage.

+ +

Let's look at an example — a simple box styled with CSS, which has some styling provided by various CSS3 features:

+ +

+ +
+

Note: You can also see this example running live on GitHub as button-with-fallback.html (also see the source code).

+
+ +

The button has a number of declarations that style, but the two we are most interested in are as follows:

+ +
button {
+  ...
+
+  background-color: #ff0000;
+  background-color: rgba(255,0,0,1);
+  box-shadow: inset 1px 1px 3px rgba(255,255,255,0.4),
+              inset -1px -1px 3px rgba(0,0,0,0.4);
+}
+
+button:hover {
+  background-color: rgba(255,0,0,0.5);
+}
+
+button:active {
+  box-shadow: inset 1px 1px 3px rgba(0,0,0,0.4),
+              inset -1px -1px 3px rgba(255,255,255,0.4);
+}
+ +

Here we are providing an RGBA {{cssxref("background-color")}} that changes opacity on hover to give the user a hint that the button is interactive, and some semi-transparent inset {{cssxref("box-shadow")}} shades to give the button a bit of texture and depth. The trouble is that RGBA colors and box shadows don't work in IE versions older than 9 — in older versions the background just wouldn't show up at all so the text would be unreadable, no good at all!

+ +

+ +

To sort this out, we have added a second background-color declaration, which just specifies a hex color — this is supported way back in really old browsers, and acts as a fallback if the modern shiny features don't work. What happens is a browser visiting this page first applies the first background-color value; when it gets to the second background-color declaration, it will override the initial value with this value if it supports RGBA colors. If not, it will just ignore the entire declaration and move on.

+ +
+

Note: The same is true for other CSS features like media queries, @font-face and @supports blocks — if they are not supported, the browser just ignores them.

+
+ +

IE conditional comments

+ +

IE conditional comments are a modified proprietary HTML comment syntax, which can be used to selectively apply HTML code to different versions of IE. This has proven to be a very effective mechanism for fixing cross browser bugs. The syntax looks like this:

+ +
<!--[if lte IE 8]>
+  <script src="ie-fix.js"></script>
+  <link href="ie-fix.css" rel="stylesheet" type="text/css">
+<![endif]-->
+ +

This block will apply the IE-specific CSS and JavaScript only if the browser viewing the page is IE 8 or older. lte means "less than or equal to", but you can also use lt, gt, gte, ! for NOT, and other logical syntax.

+ +
+

Note: Sitepoint's Internet Explorer Conditional Comments provides a useful beginner's tutorial/reference that explains the conditional comment syntax in detail.

+
+ +

As you can see, this is especially useful for applying code fixes to old versions of IE. The use case we mentioned earlier (making modern semantic elements styleable in old versions of IE) can be achieved easily using conditional comments, for example you could put something like this in your IE stylesheet:

+ +
aside, main, article, section, nav, figure, figcaption {
+  display: block;
+}
+ +

It isn't that simple, however — you also need to create a copy of each element you want to style in the DOM via JavaScript, for them to be styleable; this is a strange quirk, and we won't bore you with the details here. For example:

+ +
var asideElem = document.createElement('aside');
+ ...
+ +

This sounds like a pain to deal with, but fortunately there is a {{glossary("polyfill")}} available that does the necessary fixes for you, and more besides — see HTML5Shiv for all the details (see manual installation for the simplest usage).

+ +

Selector support

+ +

Of course, no CSS features will apply at all if you don't use the right selectors to select the element you want to style! If you just write a selector incorrectly so the styling isn't as expected in any browser, you'll just need to troubleshoot and work out what is wrong with your selector. We find that it is helpful to inspect the element you are trying to style using your browser's dev tools, then look at the DOM tree breadcrumb trail that DOM inspectors tend to provide to see if your selector makes sense compared to it.

+ +

For example, in the Firefox dev tools, you get this kind of output at the bottom of the DOM inspector:

+ +

+ +

If for example you were trying to use this selector, you'd be able to see that it wouldn't select the input element as desired:

+ +
form > #date
+ +

(The date form input isn't directly inside the <form>; you'd be better off using a general descendant selector instead of a child selector).

+ +

However, another issue that appears in versions of IE older than 9 is that none of the newer selectors (mainly pseudo-classes and pseudo-elements like :nth-of-type, :not, ::selection, etc.) work. If you want to use these in your CSS and you need to support older IE versions, a good move is to use Keith Clark's Selectivizr library — this is a small JavaScript library that works on top of an existing JavaScript library like jQuery or MooTools.

+ +
    +
  1. To try this example, make a local copy of selectivizr-example-start.html. If you look at this running live, you'll see that it contains two paragraphs, one of which is styled. We've selected the paragraph with p:first-child, which won't work in old versions of IE.
  2. +
  3. Now download MooTools and Selectivizr, and save them in the same directory as your sample HTML.
  4. +
  5. Put the following code into the head of your HTML document, just before the opening <style> tag: +
    <script type="text/javascript" src="MooTools-Core-1.6.0.js"></script>
    +    <!--[if (gte IE 6)&(lte IE 8)]>
    +      <script type="text/javascript" src="selectivizr-min.js"></script>
    +    <![endif]-->
    +
  6. +
+ +
    +
  1.  
  2. +
+ +

If you try running this in an old version of IE, it should work fine.

+ +

+ +

Handling CSS prefixes

+ +

Another set of problems comes with CSS prefixes — these are a mechanism orignally used to allow browser vendors to implement their own version of a CSS (or JavaScript) feature while the technology is in an experimental state, so they can play with it and get it right without conflicting with other browser's implementations, or the final unprefixed implementations. So for example:

+ + + +

Here's some examples:

+ +
-webkit-transform: rotate(90deg);
+
+background-image: -moz-linear-gradient(left,green,yellow);
+background-image: -webkit-gradient(linear,left center,right center,from(green),to(yellow));
+background-image: linear-gradient(to right,green,yellow);
+ +

The first line shows a {{cssxref("transform")}} property with a -webkit- prefix — this was needed to make transforms work in Chrome, etc. until the feature was finalized and such browsers added a prefix-free version of the property (at the time of writing, Chrome supported both versions).

+ +

The last three lines show three different versions of the linear-gradient() function, which is used to generate a linear gradient in the background of an element:

+ +
    +
  1. The first one has a -moz- prefix, and shows a slightly older version of the syntax (Firefox)
  2. +
  3. The second one has a -webkit- prefix, and shows an even older, proprietary version of the syntax (this is actually from a really old version of the WebKit engine).
  4. +
  5. The third one has no prefix, and shows the final version of the syntax (included in the CSS Image Values and Replaced Content Module Level 3 spec, which defines this feature).
  6. +
+ +

Prefixed features were never supposed to be used in production websites — they are subject to change or removal without warning, and cause cross browser issues. This is particularly a problem when developers decide to only use say, the -webkit- version of a property — meaning that the site won't work in other browsers. This actually happens so much that other browsers have started to implement -webkit- prefixed versions of various CSS properties, so they will work with such code. Usage of prefixes by browser vendors has declined recently precisely because of these types of problems, but there are still some that need attention.

+ +

If you insist on using prefixed features, make sure you use the right ones. You can look up what browsers require prefixes on MDN reference pages, and sites like caniuse.com. If you are unsure, you can also find out by doing some testing directly in browsers.

+ +

Try this simple example:

+ +
    +
  1. Open up google.com, or another site that has a prominent heading or other block level element.
  2. +
  3. Right/Cmd + click on the element in question and choose Inspect/Inspect element (or whatever the option is in your browser) — this should open up the dev tools in your browser, with the element highlighted in the DOM inspector.
  4. +
  5. Look for a feature you can use to select that element. For example, at the time of writing, the main Google logo had an ID of hplogo.
  6. +
  7. Store a reference to this element in a variable, for example: +
    var test = document.getElementById('hplogo');
    +
  8. +
+ + + +
    +
  1.  
  2. +
+ +

As you start to type the property name representation after the second dot (note that in JavaScript, CSS property names are written in lower camel case, not hyphenated), the JavaScript console should begin to autocomplete the names of the properties that exist in the browser and match what you've written so far. This is useful for finding out what versions of the property are implemented in that browser.

+ +

At the time of writing, both Firefox and Chrome implemented -webkit- prefixed and non-prefixed versions of {{cssxref("transform")}}!

+ +

Once you've found out which prefixes you need to support, you should write them all out in your CSS, for example:

+ +
-ms-transform: rotate(90deg);
+-webkit-transform: rotate(90deg);
+transform: rotate(90deg);
+ +

This ensures that all browsers that support any of the above forms of the property can make the feature work. It is worth putting the non-prefixed version last, because that will be the most up-to-date version, which you'll want browsers to use if possible. If for example a browser implements both the -webkit- version and the non-prefixed version,  it will first apply the -webkit- version, then override it with the non-prefixed version. You want it to happen this way round, not the other way round.

+ +

Of course, doing this for lots of different CSS rules can get really tedious. It is better to use an automation tool to do it for you. And such tools exist:

+ +

The prefix-free JavaScript library can be attached to a page, and will automatically detect what capabilities are possessed by browsers viewing the page and add prefixes as appropriate. It is really easy and convenient to use, although it does have some downsides (see the link above for details), and it is arguable that parsing every stylesheet in your site and add prefixes at run time can be a drain on the computer's processing power for a large site.

+ +

Another solution is to add prefixes automatically during development, and this (and other things besides) can be done using tools like Autoprefixer and PostCSS. These tools can be used in a variety of ways, for example Autoprefixer has an online version that allows you to enter your non-prefixed CSS on the left, and gives you a prefix-added version on the right. You can choose which browsers you want to make sure you support using the notation outlined in Autoprefixer options; also see Browserslist queries, which this is based on, for more detail. As an example, the following query will select the last 2 versions of all major browsers and versions of IE above 9.

+ +
last 2 versions, ie > 9
+ +

Autoprefixer can also be used in other, more convenient ways — see Autoprefixer usage. For example you can use it with a task runner/build tool such as Gulp or Webpack to automatically add prefixes once development has been done. (Explaining how these work is somewhat beyond the scope of this article.)

+ +

You can also use a plugin for a text editor such as Atom or Sublime text. For example, in Atom:

+ +
    +
  1. You can install it by going to Preferences > Install, searching for Autoprefixer, then hitting install.
  2. +
  3. You can set a browser query by pressing the Autoprefixer Settings button and entering the query in the text field in the Settings section on the page.
  4. +
  5. In your code, you can select sections of CSS you want to add prefixes to, open the command pallette (Cmd/Ctrl + Shift + P), then type in Autoprefixer and select the Autoprefixer result that autocompletes.
  6. +
+ +

As an example, we entered the following code:

+ +
body {
+  display: flex;
+}
+ +

We highlighted it and ran the Autoprefixer command, and it replaced it with this:

+ +
body {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+}
+ +

Layout issues

+ +

Another problem that might come up is differences in layouts between browsers. Historically this used to be much more of a problem, but recently, with modern browsers tending to support CSS more consistently, layout issues tend to be more commonly associated with:

+ + + +
+

Note: Historically web developers used to use CSS files called resets, which removed all the default browser styling applied to HTML, and then applied their own styles for everything over the top — this was done to make styling on a project more consistent, and reduce possible cross browser issues, especially for things like layout. However, it has more recently been seen as overkill. The best equivalent we have in modern times is normalize.css, a neat bit of CSS that builds slightly on the default browser styling to make things more consistent and fix some layout issues. You are advised to apply normalize.css to all your HTML pages.

+
+ +
+

Note:  When trying to track down a tricky layout issue, a good technique is to add a brightly colored {{cssxref("outline")}} to the offending element, or all the elements nearby. This makes it a lot easier to see where everything is placed. See Debug your CSS with outline visualizations for more details.

+
+ +

Support for new layout features

+ +

Much of the layout work on the web today is done using floats — this is because floats are well-supported (way back to IE4, albeit with a number of bugs that would also need to be investigated if you were to try to support IE that far back). However, they are not really meant for layout purposes — using floats the way we do is really a hack — and they do have some serious limitations (e.g. see Why Flexbox?)

+ +

More recently, dedicated layout mechanisms have appeared, like Flexbox and CSS Grids, which make common layout tasks far easier and remove such shortcomings. These however are not as well-supported in browsers:

+ + + +

Layout features aren't as easy to provide graceful fallbacks for than simple colors, shadows, or gradients. If layout properties are ignored, your entire design will likely fall to pieces. Because of this, you need to use feature detection to detect whether visiting browsers support those layout features, and selectively apply different layouts depending on the result (we will cover feature detection in detail in a later article).

+ +

For example, you could apply a flexbox layout to modern browsers, then instead apply a floated layout to older browsers that don't support flexbox.

+ +
+

Note: There is a fairly new feature in CSS called @supports, which allows you to implement native feature detection tests.

+
+ +

Responsive design problems

+ +

Responsive design is the practice of creating web layouts that change to suit different device form factors — for example different screen widths, orientations (portrait or landscape), or resolutions. A desktop layout for example will look terrible when viewed on a mobile device, so you need to provide a suitable mobile layout using media queries, and make sure it is applied correctly using viewport. You can find a detailed account of such practices in The building blocks of responsive design.

+ +

Resolution is a big issue too — for example, mobile devices are less likely to need big heavy images than desktop computers, and are more likely to have slower internet connections and possibly even expensive data plans that make wasted bandwidth more of a problem. In addition, different devices can have a range of different resolutions, meaning that smaller images could appear pixellated. There are a number of techniques that allow you to work around such problems, from simple mobile first media queries, to more complex responsive image techniques.

+ +

Another difficulty that can present problems is browser support for the features that make the above techniques possible. media queries are not supported in IE 8 or less, so if you want to use a mobile first layout and have the desktop layout then apply to old IE versions, you'll have to apply a media query {{glossary("polyfill")}} to your page, like css3-mediaqueries-js, or Respond.js.

+ +

Finding help

+ +

There are many other issues you'll encounter with HTML and CSS; the most important thing to know really is how to find answers online.

+ +

Among the best sources of support information are the Mozilla Developer Network (that's where you are now!), stackoverflow.com, and caniuse.com.

+ +

To use the Mozilla Developer Network (MDN), most people do a search engine search of the technology they are trying to find information on, plus the term "mdn", for example "mdn HTML5 video". MDN contains several useful types of content:

+ + + +

caniuse.com provides support information, along with a few useful external resource links. For example, see http://caniuse.com/#search=video (you just have to enter the feature you are searching for into the text box).

+ +

stackoverflow.com (SO) is a forum site where you can ask questions and have fellow developers share their solutions, look up previous posts, and help other developers. You are advised to look and see if there is an answer to your question already, before posting a new question. For example, we searched for "cross browser html5 video" on SO, and very quickly came up with HTML5 Video with full cross browser compatibility.

+ +

Aside from that, try searching your favourite search engine for an answer to your problem. It is often useful to search for specific error messages if you have them — other developers will be likely to have had the same problems as you.

+ +

まとめ

+ +

Now you should be familiar with the main types of cross browser HTML and CSS problems that you'll meet in web development, and how to go about fixing them.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies","Learn/Tools_and_testing/Cross_browser_testing/JavaScript", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/index.html new file mode 100644 index 0000000000..d3a0da5fa8 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/index.html @@ -0,0 +1,47 @@ +--- +title: クロスブラウザテスト +slug: Learn/Tools_and_testing/Cross_browser_testing +tags: + - Accessibility + - Automation + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Landing + - Learn + - Module + - Testing + - Tools + - cross browser +translation_of: Learn/Tools_and_testing/Cross_browser_testing +--- +
{{LearnSidebar}}
+ +

このモジュールでは、色々なウェブブラウザー間でウェブプロジェクトをテストすることに焦点を当てます。あなたのターゲット視聴者 (例 どのユーザー、ブラウザー、デバイスに一番関心があるのか?) の特定や、テストをどう動かすかや、主な問題としてさまざまな種類のコードと対面してそれらを緩和する方法や、テストを楽にして問題を解決するのに最も役立つツールが何かや、自動化を利用してテストをスピードアップする方法を見て行きます。

+ +

前提条件

+ +

ここで述べるツールを使ってみる前に、基本的な HTMLCSSJavaScript 言語をよく理解しておきます。

+ +

ガイド

+ +
+
はじめてのクロスブラウザーテスト
+
この記事ではクロスブラウザーテストの概観を提供し始めます。その過程で「ブラウザーテストとは何?」「どんな種類の問題によく出くわしますか?」「テストと、問題の特定・修正の主なアプローチは?」といった質問に答えたりします。
+
テスト実行戦略
+
次に、テスト実行について掘り下げ、ターゲット視聴者(例、どのブラウザー、デバイス、その他のセグメントでテストを確実にするのか)を特定し、ローファイテスト戦略(ある範囲のデバイスと仮装マシンにて必要ならアドホックテストを行う)、高度なテスト戦略(専用テストアプリを使った自動化)、ユーザーグループを使ったテストまで見て行きます。
+
よくあるHTML や CSS の問題を扱う
+
シーンがセットされたら、HTMLとCSSコードの中でよく出くわすクロスブラウザー問題と、問題を防いだり、問題発生を修正するのに使えるツールを詳しく見ていきます。これにはコードの lint や、CSSプレフィックスを手渡したり、問題を監視するブラウザーの開発ツールを使ったり、ブラウザーサポート追加に polyfill を使ったり、レスポンシブデザインの問題に取り組んだり、といった事が含まれます
+
よくある JavaScript の問題を扱う
+
今度はクロスブラウザー JavaScript の問題と、その修正方法を見て行きます。ここにはブラウザーの開発ツールを使って問題を突き止めて修正したり、問題を回避するのに pollyfill やライブラリーを使用したり、古いブラウザーの対応にモダン JavaScript の機能を掴んだり、といった事が含まれます。
+
よくあるアクセシビリティの問題を扱う
+
次にアクセシビリティに注意を向けて、良くある問題の情報、簡単なテスト実施の方法、アクセシビリティの問題を見つけるための監査/自動化ツールの利用方法を提供します。
+
機能検出の実装
+
機能検出はブラウザーがあるコードブロックをサポートしているか考えたり、サポートする/しないによって他のコードを実行したりして、いくつかのブラウザーでクラッシュ/エラー起こすことなく、常に動作の体験を提供できるようにすることです。この記事では簡単な機能検出を書く方法や、 @supports のようなネイティブ機能について詳しく記載します。
+
はじめての自動テスト
+
いくつかのブラウザーと端末で、一日に何度もテストを手動実行するのはつまらないし時間をつぶします。これを効率良く扱うには、自動化ツールに詳しくなるべきです。この記事では何を入手できるかや、タスクランナーの使い方や、Sauce Labs と Browser Stack のような商用ブラウザーテスト自動化ツールの使い方の基本を見て行きます。
+
テスト自動化環境をセットアップする
+
この記事では、Selenium/WebDriver や selenium-webdriver for Node のようなテストライブラリーを使って、自動化環境のインストールとテストを実行する方法を教えます。またあなたのローカルテスト環境と、以前の記事で見てきたような商用アプリとを統合する方法についても見て行きます。
+
diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html new file mode 100644 index 0000000000..3e0e2e7834 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html @@ -0,0 +1,209 @@ +--- +title: はじめてのクロスブラウザテスト +slug: Learn/Tools_and_testing/Cross_browser_testing/Introduction +tags: + - Article + - Beginner + - CodingScripting + - Learn + - Testing + - concepts + - cross browser +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

この記事では (クロス) ブラウザテストのトピックの概要を説明し、「クロスブラウザテストとは何ですか?」、「発生する最も一般的な問題の種類は何ですか?」、「問題のテスト、特定、および修正のための主なアプローチは?」などの質問に答えながらモジュールを始めます。

+ + + + + + + + + + + + +
前提知識:HTML, CSS, JavaScript 言語の基礎に精通していること。
目的:クロスブラウザテストに関する高レベルのコンセプトを理解する。
+ +

クロスブラウザテストとは?

+ +

クロスブラウザテストは、作成した Web サイトと Web アプリケーションが許容できる数の Web ブラウザにわたって動作することを確認することです。Web 開発者として、自分のプロジェクトが機能するだけでなく、使用しているブラウザ、デバイス、その他の補助ツールに関係なく、すべてのユーザに対して機能することを確認するのはあなたの責任です。あなたは考える必要があります:

+ + + +

ユーザーの状況は一人ひとり異なってきます — 自分の Macbook Pro やハイエンドな Galaxy Nexus で動いても、すべてのユーザーにとって動作するとは限りません 。それを確認するには膨大な数のテストが必要になってきます。

+ +
+

: Make the web work for everyone では、人々が使っているさまざまなブラウザの種類やそれぞれのマーケットシェア、それに伴うクロスブラウザの懸念点などが説明されています。

+
+ +

ここでいくつかの用語を説明します。最初に、「クロスブラウザでの動作」と言う時、様々なブラウザ間で受け入れられるユーザー体験が提供されることを言います。サイトがすべてのブラウザでまったく同一の体験が提供していなくても、コア機能がいくつかの方法で受け入れられる限りは、潜在的にOKです。モダンブラウザではアニメーションや3Dや目立つものがあり、いっぽう古いブラウザでは平坦なグラフィックで同じ情報を表すだけのこともあるでしょう。サイト所有者が満足している限り、あなたの仕事は完了です。

+ +

その一方で、サイトが視力のあるユーザーにとって動作していても、視覚障がいのあるユーザーにとって、スクリーンリーダーアプリケーションがそこにある情報を読み取れないため完全にアクセスできない場合は、OKではありません。

+ +

2つ目に、「受け入れられる数のウェブブラウザ間で」と言った時、世界中のブラウザの 100% の意味ではありません — これは不可能です。ユーザーが使うブラウザや端末の情報を呼び出すことができます (このシリーズの2つ目の記事で見ていきましょう — Gotta test 'em all?を見てください)が、すべてを保証することはできません。ウェブ開発者としては、ある範囲のブラウザと端末にてコードが完全に動作することをサイトオーナーと同意しておく必要があります。しかしそれを超えて、その他のブラウザでコンテンツを使う機会をできるだけ与えられるよう防衛的なコードを書いておく必要があります。

+ +
+

: このモジュールの後の方でも、防衛的なコードをカバーします。

+
+ +

なぜクロスブラウザ問題が起きるのか?

+ +

クロスブラウザ問題が生じる原因はたくさんあります。そして、本記事ではブラウザ・端末・ブラウザの設定によって生じる問題について述べます。クロスブラウザの問題に取り組む前に、ソース中のバグを解決するべきです(必要に応じて前述のDebugging HTML, Debugging CSS, and What went wrong? Troubleshooting JavaScriptの記事を見て記憶を呼び覚ましてください)。

+ +

クロスブラウザ問題が発生する原因は主に以下になります。

+ + + +

上記の他にも理由はあります。

+ +

後述の記事では、クロスブラウザ問題についてよくある問題について掘り下げ、解決策を提示します。

+ +

クロスブラウザテストの作業手順

+ +

All of this cross browser testing business may sound time consuming and scary, but it needn't be — you just need to plan carefully for it, and make sure you do enough testing in the right places to make sure you don't run into unexpected problems. If you are working on a large project, you should be testing it regularly, to make sure that new features work for your target audience, and that new additions to the code don't break old features that were previously working.

+ +

If you leave all the testing to the end of a project, any bugs you uncover will be a lot more expensive and time consuming to fix than if you uncover them and fix them as you go along.

+ +

The workflow for testing and bug fixes on a project can be broken down into roughly the following four phases (this is only very rough — different people may do things quite differently to this):

+ +

Initial planning > Development > Testing/discovery > Fixes/iteration

+ +

Steps 2–4 will tend to be repeated as many times as necessary to get all of the implementation done. We will look at the different parts of the testing process in much greater detail in subsequent articles, but for now let's just summarize what may occur in each step.

+ +

初期計画

+ +

In the initial planning phase, you will probably have several planning meetings with the site owner/client (this might be your boss, or someone from an external company you are building a web site for), in which you determine exactly what the web site should be — what content and functionality should it have, what should it look like, etc. At this point you'll also want to know how much time you have to develop the site — what is their deadline, and how much are they going to pay you for your work? We won't go into much detail about this, but cross-browser issues can have a serious effect on such planning.

+ +

Once you've got an idea of the required featureset, and what technologies you will likely build these features with, you should start exploring the target audience — what browsers, devices, etc. will the target audience for this site be using? The client might already have data about this from previous research they've done, e.g. from other web sites they own, or from previous versions of the web site you are now working on. If not, you will be able to get a good idea by looking at other sources, such as usage stats for competitors, or countries the site will be serving. You can also use a bit of intuition.

+ +

So for example, you might be building an e-commerce site that serves customers in North America. the site should work entirely in the last few versions of the most popular desktop and mobile (iOS, Android, Windows phone) browsers — this should include Chrome (and Opera as it is based on the same rendering engine as Chrome), Firefox, IE/Edge, and Safari. It should also provide an acceptable experience on IE 8 and 9, and be accessible with WCAG AA compliance.

+ +

Now you know your target testing platforms, you should go back and review the required featureset and what technologies you are going to use. For example, if the e-commerce site owner wants a WebGL-powered 3D tour of each product built into the product pages, they will need to accept that this just won't work in IE versions before 11. You'd have to agree to provide a version of the site without this feature to users of older IE versions.

+ +

You should compile a list of the potential problem areas.

+ +
+

: You can find browser support information for technologies by looking up the different features on MDN — the site you're on! You should also consult caniuse.com, for some further useful details.

+
+ +

Once you've agreed on these details, you can go ahead and start developing the site.

+ +

開発

+ +

Now on to the development of the site. You should split the different parts of the development into modules, for example you might split the different site areas up — home page, product page, shopping cart, payment workflow, etc. You might then further subdivide these — implement common site header and footer, implement product page detail view, implement persistent shopping cart widget, etc.

+ +

There are multiple general strategies to cross browser development, for example:

+ + + +

Normally your development will involve a combination of the above three approaches. The most important thing is that you test each small part before committing it — don't leave all the testing till the end!

+ +

テスト/発見

+ +

After each implementation phase, you will need to test the new functionality. To start with, you should make sure there are no general issues with your code that are stopping your feature from working:

+ +
    +
  1. Test it in a couple of stable browsers on your system, like Firefox, Safari, Chrome, or IE/Edge.
  2. +
  3. Do some low fi accessibility testing, such as trying to use your site with only the keyboard, or using your site via a screen reader to see if it is navigable.
  4. +
  5. Test on a mobile platform, such as Android or iOS.
  6. +
+ +

At this point, fix any problems you find with your new code.

+ +

Next, you should try expanding your list of test browsers to a full list of target audience browsers and start concentrating on weeding out cross browser issues (see the next article for more information on determining your target browsers). For example:

+ + + +

The most low fi option is to just do all the testing you can by yourself (pulling in team mates to help out if you are working in a  team). You should try to test it on real physical devices where possible.

+ +

If you haven't got the means to test all those different browser, operating system, and device combinations on physical hardware, you can also make use of emulators (emulate a device using software on your desktop computer) and virtual machines (software that allows you to emulate multiple operating system/software combinations on your desktop computer). This is a very popular choice, especially in some circumstances — for example, Windows doesn't let you have multiple versions of Windows installed simulataneously on the same machine, so using multiple virtual machines is often the only option here.

+ +

Another option is user groups — using a group of people outside your development team to test your site. This could be a group of friends or family, a group of other employees, a class at a local university, or a professional user testing setup, where people are paid to test out your site and provide results.

+ +

Finally, you can get smarter with your testing using auditing or automation tools; this is a sensible choice as your projects get bigger, as doing all this testing by hand can start to take a really long time. You can set up your own testing automation system (Selenium being the popular app of choice) that could for example load your site in a number of different browsers, and:

+ + + +

You can also go further than this, if wished. There are commercial tools available such as Sauce Labs, Browser StackLambdaTest, TestingBot, and CrossBrowserTesting that do this kind of thing for you, without you having to worry about the setup, if you wish to invest some money in your testing. It is also possible to set up an environment that automatically runs tests for you, and then only lets you check in your changes to the central code repository if the tests still pass.

+ +

Testing on prerelease browsers

+ +

It is often a good idea to test on prerelease versions of browsers; see the following links:

+ + + +

This is especially prevalent if you are using very new technologies in your site, and you want to test against the latest implementations, or if you are coming across a bug in the latest release version of a browser, and you want to see if the browser's developers have fixed the bug in a newer version.

+ +

修正/繰り返し

+ +

Once you've discovered a bug, you need to try to fix it.

+ +

The first thing to do is to narrow down where the bug occurs as much as possible. Get as much information as you can from the person reporting the bug — what platform(s), device(s), browser version(s), etc. Try it on similar configurations (e.g. the same browser version on different desktop platforms, or a few different versions of the same browser on the same platform) to see how widely the bug persists.

+ +

It might not be your fault — if a bug exists in a browser, then hopefully the vendor will rapidly fix it. It might have already been fixed — for example if a bug is present in Firefox release 49, but it is no longer there in Firefox Nightly (version 52), then they have fixed it. If it is not fixed, then you may want to file a bug (see {{anch("Reporting bugs")}}, below).

+ +

If it is your fault, you need to fix it! Finding out the cause of the bug involves the same strategy as any web development bug (again, see Debugging HTML, Debugging CSS, and What went wrong? Troubleshooting JavaScript). Once you've discovered what is causing your bug, you need to decide how to work around it in the particular browser it is causing problems in — you can't just change the problem code outright, as this may break the code in other browsers. The general approach is usually to fork the code in some way, for example use JavaScript feature detection code to detect situations in which a problem feature doesn't work, and run some different code in those cases that does work.

+ +

Once a fix has been made, you'll want to repeat your testing process to make sure your fix is working OK, and hasn't caused the site to break in other places or in other browsers.

+ +

バグを報告する

+ +

ブラウザでバグを発見した場合は、上記で述べたことを繰り返しますが、それらを報告する必要があります。

+ + + +

要約

+ +

この記事では、クロスブラウザテストに関して知っておくべき最も大事な概念について、高位の理解を与えてきました。この知識を備えたことで、クロスブラウザテストの戦略について学び始める準備ができています。

+ +

{{NextMenu("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html new file mode 100644 index 0000000000..12c8f274d6 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html @@ -0,0 +1,521 @@ +--- +title: JavaScript のよくある問題を扱う +slug: Learn/Tools_and_testing/Cross_browser_testing/JavaScript +tags: + - Article + - Beginner + - CodingScripting + - JavaScript + - Learn + - Libraries + - Testing + - cross browser + - feature detection + - linting + - polyfills +translation_of: Learn/Tools_and_testing/Cross_browser_testing/JavaScript +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS","Learn/Tools_and_testing/Cross_browser_testing/Accessibility", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

ここではよくあるクロスブラウザー JavaScript 問題と、その直し方を見てみます。これにはブラウザーの開発ツールを使って問題をつきとめて修正したり、問題の回避に Polyfills やライブラリーを使ったりモダンな JavaScript 機能を古いブラウザーで使ったりなどです。

+ + + + + + + + + + + + +
前提知識:Familiarity with the core HTML, CSS, and JavaScript languages; an idea of the high-level principles of cross browser testing.
狙い:To be able to diagnose common JavaScript cross-browser problems, and use appropriate tools and techniques to fix them.
+ +

JavaScript のトラブル

+ +

Historically, JavaScript was plagued with cross-browser compatibility problems — back in the 1990s, the main browser choices back then (Internet Explorer and Netscape) had scripting implemented in different language flavours (Netscape had JavaScript, IE had JScript and also offered VBScript as an option), and while at least JavaScript and JScript were compatible to some degree (both based on the {{glossary("ECMAScript")}} specification), things were often implemented in conflicting, incompatible ways, causing developers many nightmares.

+ +

Such incompatibility problems persisted well into the early 2000s, as old browsers were still being used and still needed supporting. This is one of the main reasons why libraries like jQuery came into existence — to abstract away differences in browser implementations (e.g. see the code snippet in How to make an HTTP request) so developers only have to write one simple bit of code (see jQuery.ajax()). jQuery (or whatever library you are using) will then handle the differences in the background, so you don't have to.

+ +

Things have got much better since then; modern browsers do a good job of supporting "classic JavaScript features", and the requirement to use such code has diminished as the requirement to support older browsers has lessened (although bear in mind that they have not gone away altogether).

+ +

These days, most cross-browser JavaScript problems are seen:

+ + + +

We'll explore all these problems and more below.

+ +

一般的な JavaScript の問題を修正する

+ +

As we said in the previous article on HTML/CSS, you should make sure your code is working generally, before going on to concentrate on the cross-browser issues. If you are not already familiar with the basics of Troubleshooting JavaScript, you should study that article before moving on. There are a number of common JavaScript problems that you will want to be mindful of, such as:

+ + + +
+

Buggy JavaScript Code: The 10 Most Common Mistakes JavaScript Developers Make has some nice discussions of these common mistakes and more.

+
+ +

Linters

+ +

HTML や CSSと同じく、良い品質を保つことができて、エラーを示して悪いやり方の警告をつけ、エラー/警告の報告を厳しくもゆるくも変えられる Linterを使ってエラーがちな JavaScript コードを減らすことが確実にできます。我々が勧める JavaScript/ECMAScript linters は JSHintESLint; これらは色々な方法で使用でき、そのいくつかを以下で紹介します。

+ +

オンライン

+ +

The JSHint homepage provides an online linter, which allows you to enter your JavaScript code on the left and provides an output on the right, including metrics, warnings, and errors.

+ +

+ +

コードエディターのプラグイン

+ +

It is not very convenient to have to copy and paste your code over to a web page to check its validity several times. What you really want is a linter that will fit into your standard workflow with the minimum of hassle. Many code editors have linter plugins, for example Github's Atom code editor has a JSHint plugin available.

+ +

To install it:

+ +
    +
  1. Install Atom (if you haven't got an up-to-date version already installed) — download it from the Atom page linked above.
  2. +
  3. Go to Atom's Preferences... dialog (e.g. by Choosing Atom > Preferences... on Mac, or File > Preferences... on Windows/Linux) and choose the Install option in the left-hand menu.
  4. +
  5. In the Search packages text field, type "jslint" and press Enter/Return to search for linting-related packages.
  6. +
  7. You should see a package called lint at the top of the list. Install this first (using the Install button), as other linters rely on it to work. After that, install the linter-jshint plugin.
  8. +
  9. After the packages have finished installing, try loading up a JavaScript file: you'll see any issues highlighted with green (for warnings) and red (for errors) circles next to the line numbers, and a separate panel at the bottom provides line numbers, error messages, and sometimes suggested values or other fixes.
  10. +
+ +

Other popular editors have similar linting packages available. For example, see the "Plugins for text editors and IDEs"  section of the JSHint install page.

+ +

その他

+ +

There are other ways to use such linters; you can read about them on the JSHint and ESLint install pages.

+ +

It is worth mentioning command line uses — you can install these tools as command line utilities (available via the CLI — command line interface) using npm (Node Package Manager — you'll have to install NodeJS first). For example, the following command installs JSHint:

+ +
npm install -g jshint
+
+ +

You can then point these tools at JavaScript files you want to lint, for example:

+ +

You can also use these tools with a task runner/build tool such as Gulp or Webpack to automatically lint your JavaScript during development. (see Using a task runner to automate testing tools in a later article.) See ESLint integrations for ESLint options; JSHint is supported out of the box by Grunt, and also has other integrations available, e.g. JSHint loader for Webpack.

+ +
+

: ESLint takes a bit more setup and configuration than JSHint, but it is more powerful too.

+
+ +

ブラウザーの開発ツール

+ +

Browser developer tools have many useful features for helping to debug JavaScript. For a start, the JavaScript console will report errors in your code.

+ +

Make a local copy of our broken-ajax.html example (see the source code also). If you look at the console, you'll see the following output:

+ +

+ +

The error message reads "TypeError: jsonObj is null", and the line number signified is line 37. If we look at the source code, the relevant code section is this:

+ +
function populateHeader(jsonObj) {
+  var myH1 = document.createElement('h1');
+  myH1.textContent = jsonObj['squadName'];
+  header.appendChild(myH1);
+
+  ...
+ +

So the code falls over as soon as we try to access jsonObj (which as you might expect, is supposed to be a JSON object). This is supposed to be fetched from an external .json file using the following XMLHttpRequest call:

+ +
var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
+var request = new XMLHttpRequest();
+request.open('GET', requestURL);
+request.send();
+
+var superHeroes = request.response;
+populateHeader(superHeroes);
+showHeroes(superHeroes);
+ +

But this fails.

+ +

コンソール API

+ +

You may already know what is wrong with this code, but let's explore it some more to show how you could investigate this. For a start, there is a Console API that allows JavaScript code to interact with the browser's JavaScript console. It has a number of features available, but the main one you'll use often is console.log(), which prints a custom message to the console.

+ +

Try inserting the following line just below line 31 (bolded above):

+ +
console.log('Response value: ' + superHeroes);
+ +

Refresh the page in the browser, and you will get an output in the console like so:

+ +

+ +

The console.log() output shows that the superHeroes object doesn't appear to contain anything, although note that the error message has now changed, to "TypeError: heroes is undefined". This shows that the error is intermittent, giving further evidence that this is some kind of asynchronous error. Let's fix the current error and move on — remove the console.log() line, and update this code block:

+ +
var superHeroes = request.response;
+populateHeader(superHeroes);
+showHeroes(superHeroes);
+ +

to the following:

+ +
request.onload = function() {
+  var superHeroes = request.response;
+  populateHeader(superHeroes);
+  showHeroes(superHeroes);
+}
+ +

This solves the asynchronous issue, by ensuring that the functions are not run and passed the superHeroes object until the response has finished loading and is available.

+ +

So to summarize, anytime something is not working and a value does not appear to be what it is meant to be at some point in your code, you can use console.log() to print it out and see what is happening.

+ +

JavaScript デバッガーを使う

+ +

We have solved one problem, but we are still stuck with the error message "TypeError: heroes is undefined", reported on line 51. Let's investigate this now, using a more sophisticated feature of browser developer tools: the JavaScript debugger as it is called in Firefox.

+ +
+

: Similar tools are available in other browsers; the Sources tab in Chrome, Debugger in Safari (see Safari Web Development Tools), etc.

+
+ +

In Firefox, the Debugger tab looks as follows:

+ +

+ + + +

The main feature of such tools is the ability to add breakpoints to code — these are points where the execution of the code stops, and at that point you can examine the environment in its current state and see what is going on.

+ +

Let's get to work. First of all, we know that the error is being thrown at line 51. Click on line number 51 in the center panel to add a breakpoint to it (you'll see a blue arrow appear over the top of it). Now refresh the page (Cmd/Ctrl + R) — the browser will pause execution of the code at line 51. At this point, the right-hand side will update to show some very useful information.

+ +

+ + + +

We can find out some very useful information in here.

+ +
    +
  1. Expand the showHeroes scope — you can see from this that the heroes variable is undefined, indicating that accessing the members property of jsonObj (first line of the function) didn't work.
  2. +
  3. You can also see that the jsonObj variable is storing a text string, not a JSON object.
  4. +
  5. Exploring further down the call stack, click request.onload in the Call Stack section. The view will update to show the request.onload function in the center panel, and its scopes in the Scopes section.
  6. +
  7. Now if you expand the request.onload scope, you'll see that the superHeroes variable is a text string too, not an object. This settles it — our XMLHttpRequest call is returning the JSON as text, not JSON.
  8. +
+ +
+

: We'd like you to try fixing this problem yourself. To give you a clue, you can either tell the XMLHttpRequest object explicitly to return JSON format, or convert the returned text to JSON after the response arrives. If you get stuck, consult our fixed-ajax.html example.

+
+ +
+

: The debugger tab has many other useful features that we've not discussed here, for example conditional breakpoints and watch expressions. For a lot more information, see the Debugger page.

+
+ +

パフォーマンスの問題

+ +

As your apps get more complex and you start to use more JavaScript, you may start to run into performance problems, especially when viewing apps on slower devices. Performance is a big topic, and we don't have time to cover it in detail here. Some quick tips are as follows:

+ + + +
+

: Addy Osmani's Writing Fast, Memory-Efficient JavaScript contains a lot of detail and some excellent tips for boosting JavaScript performance.

+
+ +

クロスブラウザー JavaScript の問題

+ +

In this section, we'll look at some of the more common cross-browser JavaScript problems. We'll break this down into:

+ + + +

モダン JavaScript/API 機能を使う

+ +

In the previous article we described some of the ways in which HTML and CSS errors and unrecognized features can be handled due to the nature of the languages. JavaScript is not as permissive as HTML and CSS however — if the JavaScript engine encounters mistakes or unrecognized syntax, more often than not it will throw errors.

+ +

There are a number of modern JavaScript language features defined in recent versions of the specs (ECMAScript 6 / ECMAScript Next) that simply won't work in older browsers. Some of these are syntactic sugar (basically an easier, nicer way of writing what you can already do using existing features), and some offer interesting new possibilities.

+ +

For example:

+ + + +

There are also many new APIs appearing in recent browsers, which don't work in older browsers, for example:

+ + + +

There are a few strategies for handling incompatibilities between browsers relating to feature support; let's explore the most common ones.

+ +
+

: These strategies do not exist in separate silos — you can, of course combine them as needed. For example, you could use feature detection to determine whether a feature is supported; if it isn't, you could then run code to load a polyfill or a library to handle the lack of support.

+
+ +

機能検出

+ +

The idea behind feature detection is that you can run a test to determine whether a JavaScript feature is supported in the current browser, and then conditionally run code to provide an acceptable experience both in browsers that do and don't support the feature. As a quick example, the Geolocation API  (which exposes available location data for the device the web browser is running on) has a main entry point for its use — a geolocation property available on the global Navigator object. Therefore, you can detect whether the browser supports geolocation or not by using something like the following:

+ +
if("geolocation" in navigator) {
+  navigator.geolocation.getCurrentPosition(function(position) {
+    // show the location on a map, perhaps using the Google Maps API
+  });
+} else {
+  // Give the user a choice of static maps instead perhaps
+}
+ +

You could also write such a test for a CSS feature, for example by testing for the existence of element.style.property (e.g. paragraph.style.transform !== undefined). But for both CSS and JavaScript, it is probably better to use an established feature detection library rather than writing your own all the time. Modernizr is the industry standard for feature detection tests.

+ +

As a last point, don't confuse feature detection with browser sniffing (detecting what specific browser is accessing the site) — this is a terrible practice that should be discouraged at all costs. See {{anch("Using bad browser sniffing code")}}, later on, for more details.

+ +
+

: Some features are known to be undetectable — see Modernizr's list of Undetectables.

+
+ +
+

: Feature detection will be covered in a lot more detail in its own dedicated article, later in the module.

+
+ +

ライブラリー

+ +

JavaScript libraries are essentially third party units of code that you can attach to your page, providing you with a wealth of ready-made functionality that can be used straight away, saving you a lot of time in the process. A lot of JavaScript libraries probably came into existence because their developer was writing a set of common utility functions to save them time when writing future projects, and decided to release them into the wild because other people might find them useful too.

+ +

JavaScript libraries tend to come in a few main varieties (some libraries will serve more than one of these purposes):

+ + + +

When choosing a library to use, make sure that it works across the set of browsers you want to support, and test your implementation thoroughly. Also make sure that the library is popular and well-supported, and isn't likely to just become obsolete next week. Talk to other developers to find out what they recommend, see how much activity and how many contributors the library has on Github (or wherever else it is stored), etc.

+ +
+

: JavaScripting.com gives you a good idea of just how many JavaScript libraries there are available, and can be useful for finding libraries for specific purposes.

+
+ +

Library usage at a basic level tends to consist of downloading the library's files (JavaScript, possibly some CSS or other dependencies too) and attaching them to your page (e.g. via a {{htmlelement("script")}} element), although there are normally many other usage options for such libraries, like installing them as Bower components, or including them as dependencies via the Webpack module bundler. You will have to read the libraries' individual install pages for more information.

+ +
+

: You will also come across JavaScript frameworks in your travels around the Web, like Ember and Angular. Whereas libraries are often usable for solving individual problems and dropping into existing sites, frameworks tend to be more along the lines of complete solutions for developing complex web applications.

+
+ +

Polyfills

+ +

Polyfills also consist of 3rd party JavaScript files that you can drop into your project, but they differ from libraries — whereas libraries tend to enhance existing functionality and make things easier, polyfills provide functionality that doesn't exist at all. Polyfills use JavaScript or other technologies entirely to build in support for a feature that a browser doesn't support natively. For example, you might use a polyfill like es6-promise to make promises work in browsers where they are not supported natively.

+ +

Modernizr's list of HTML5 Cross Browser Polyfills is a useful place to find polyfills for different purposes. Again, you should research them before you use them — make sure they work and are maintained.

+ +

Let's work through an exercise — in this example we will use a Fetch polyfill to provide support for the Fetch API in older browsers; however we also need to use the es6-promise polyfill, as Fetch makes heavy use of promises, and browsers that don't support them will still be in trouble.

+ +
    +
  1. To get started, make a local copy of our fetch-polyfill.html example and our nice image of some flowers in a new directory. We are going to write code to fetch the flowers image and display it in the page.
  2. +
  3. Next, save copies of the Fetch polyfill and the es6-promises polyfill in the same directory as the HTML.
  4. +
  5. Apply the polyfill scripts to the page using the following code — place these above the existing {{htmlelement("script")}} element so they will be available on the page already when we start trying to use Fetch: +
    <script src="es6-promise.js"></script>
    +<script src="fetch.js"></script>
    +
  6. +
  7. Inside the original {{htmlelement("script")}}, add the following code:
  8. +
  9. +
    var myImage = document.querySelector('.my-image');
    +
    +fetch('flowers.jpg').then(function(response) {
    +  response.blob().then(function(myBlob) {
    +    var objectURL = URL.createObjectURL(myBlob);
    +    myImage.src = objectURL;
    +  });
    +});
    +
  10. +
  11. Now if you load it in a browser that doesn't support Fetch (Safari and IE are obvious candidates), you should still see the flower image appear — cool! 
    +
  12. +
+ +
+

: You can find our finished version at fetch-polyfill-finished.html (see also the source code).

+
+ +
+

: Again, there are many different ways to make use of the different polyfills you will encounter — consult each polyfill's individual documentation.

+
+ +

One thing you might be thinking is "why should we always load the polyfill code, even if we don't need it?" This is a good point — as your sites get more complex and you start to use more libraries, polyfills, etc., you can start to load a lot of extra code, which can start to affect performance, especially on less-powerful devices. It makes sense to only load files as needed.

+ +

Doing this requires some extra setup in your JavaScript. You need some kind of a feature detection test that detects whether the browser supports the feature we are trying to use:

+ +
if (browserSupportsAllFeatures()) {
+  main();
+} else {
+  loadScript('polyfills.js', main);
+}
+
+function main(err) {
+  // actual app code goes in here
+}
+ +

So first we run a conditional that checks whether the function browserSupportsAllFeatures() returns true. If it does, we run the main() function, which will contain all our app's code. browserSupportsAllFeatures() looks like this:

+ +
function browserSupportsAllFeatures() {
+  return window.Promise && window.fetch;
+}
+ +

Here we are testing whether the Promise object and fetch() function exist in the browser. If both do, the function returns true. If the function returns false, then we run the code inside the second part of the conditional  — this runs a function called loadScript(), which loads the polyfills into the page, then runs main() after the loading has finished. loadScript() looks like this:

+ +
function loadScript(src, done) {
+  var js = document.createElement('script');
+  js.src = src;
+  js.onload = function() {
+    done();
+  };
+  js.onerror = function() {
+    done(new Error('Failed to load script ' + src));
+  };
+  document.head.appendChild(js);
+}
+
+ +

This function creates a new <script> element, then sets its src attribute to the path we specified as the first argument ('polyfills.js' when we called it in the code above). When it has loaded, we run the function we specified as the second argument (main()). If an error occurs in the loading of the script, we still call the function, but with a custom error that we can retrieve to help debug a problem if it occurs.

+ +

Note that polyfills.js is basically the two polyfills we are using put together into one file. We did this manually, but there are cleverer solutions that will automatically generate bundles for you — see Browserify (see Getting started with Browserify for a basic tutorial). It is a good idea to bundle JS files into one like this — reducing the number of HTTP requests you need to make improves the performance of your site.

+ +

You can see this code in action in fetch-polyfill-only-when-needed.html (see the source code also). We'd like to make it clear that we can't take credit for this code — it was originally written by Philip Walton.  Check out his article Loading Polyfills Only When Needed for the original code, plus a lot of useful explanation around the wider subject).

+ +
+

: There are some 3rd party options to consider, for example Polyfill.io — this is a meta-polyfill library that will look at each browser's capabilities and apply polyfills as needed, depending on what APIs and JS features you are using in your code.

+
+ +

JavaScript トランスパイルする

+ +

Another option that is becoming popular for people that want to use modern JavaScript features now is converting code that makes use of ECMAScript 6/ECMAScript 2015 features to a version that will work in older browsers.

+ +
+

: This is called "transpiling" — you are not compiling code into a lower level for to be run on a computer (like you would say with C code); instead, you are changing it into a syntax that exists at a similar level of abstraction so it can be used in the same way, but in slightly different circumstances (in this case, transforming one flavor of JavaScript into another).

+
+ +

So for example, we talked about arrow functions (see arrow-function.html live, and see the source code) earlier in the article, which only work in the newest browsers:

+ +
() => { ... }
+ +

We could transpile this across to a traditional old-fashioned anonymous function, so it would work in older browsers:

+ +
function() { ... }
+ +

The recommended tool for JavaScript transpiling is currently Babel. This offers transpilation capabilities for language features that are appropriate for transpilation. For features that can't just be easily transpiled into an older equivalent, Babel also offers polyfills to provide support.

+ +

The easiest way to give Babel a try is to use the online version, which allows you to enter your source code on the left, and outputs a transpiled version on the right.

+ +
+

: There are many ways to use Babel (task runners, automation tools, etc.), as you'll see on the setup page.

+
+ +

悪いブラウザーを検出するコードを使う

+ +

All browsers have a user-agent string, which identifies what the browser is (version, name, OS, etc.) In the bad only days when pretty much everyone used Netscape or Internet Explorer, developers used to use so-called browser sniffing code to detect which browser the user was using, and give them appropriate code to work on that browser.

+ +

The code used to look something like this (although this is a simplified example):

+ +
var ua = navigator.userAgent;
+
+if(ua.indexOf('Firefox') !== -1) {
+  // run Firefox-specific code
+} else if(ua.indexOf('Chrome') !== -1) {
+  // run Chrome-specific code
+}
+ +

The idea was fairly good — detect what browser is viewing the site, and run code as appropriate to make sure the browser will be able to use your site OK.

+ +
+

: Try opening up your JavaScript console now and running navigator.userAgent, to see what you get returned.

+
+ +

However, as time went on, developers started to see major problems with this approach. For a start, the code was error prone. What if you knew a feature didn't work in say, Firefox 10 and below, and implemented code to detect this, and then Firefox 11 came out — which did support that feature? Firefox 11 probably wouldn't be supported because it's not Firefox 10. You'd have to change all your sniffing code regularly.

+ +

Many developers implemented bad browser sniffing code and didn't maintain it, and browsers start getting locked out of using websites containing features that they had since implemented. This became so common that browsers started to lie about what browser they were in their user-agent strings (or claim they were all browsers), to get around sniffing code. Browsers also implemented facilities to allow users to change what user-agent string the browser reported when queried with JavaScript. This all made browser sniffing even more error prone, and ultimately pointless. 

+ +
+

: You should read History of the browser user-agent string by Aaron Andersen for a useful and amusing take on this situation.

+
+ +

The lesson to be learned here is — NEVER use browser sniffing. The only really use case for browser sniffing code in the modern day is if you are implementing a fix for a bug in a very specific version of a particular browser. But even then, most bugs get fixed pretty quickly in browser vendor rapid release cycles. It won't come up very often. {{anch("Feature detection")}} is almost always a better option — if you detect whether a feature is supported, you won't need to change your code when new browser versions come out, and the tests are much more reliable.

+ +

If you come across browser sniffing when joining an existing project, look at whether it can be replaced with something more sensible. Browser sniffing causes all kind of interesting bugs, like {{bug(1308462)}}.

+ +

JavaScript プレフィックスを扱う

+ +

In the previous article, we included quite a lot of discussion about handing CSS prefixes. Well, new JavaScript implementations sometimes use prefixes too, although JavaScript uses camel case rather than hyphenation like CSS. For example, if a prefix was being used on a new shint API object called Object:

+ + + +

Here's an example, taken from our violent-theremin demo (see source code), which uses a combination of the Canvas API and the Web Audio API to create a fun (and noisy) drawing tool:

+ +
var AudioContext = window.AudioContext || window.webkitAudioContext;
+var audioCtx = new AudioContext();
+ +

In the case of the Web Audio API, the key entry points to using the API were supported in Chrome/Opera via webkit prefixed versions (they now support the unprefixed versions). The easy way to get around this situation is to create a new version of the objects that are prefixed in some browsers, and make it equal to the non-prefixed version, OR the prefixed version (OR any other prefixed versions that need consideration) — whichever one is supported by the browser currently viewing the site will be used.

+ +

Then we use that object to manipulate the API, rather than the original one. In this case we are creating a modified AudioContext constructor, then creating a new audio context instance to use for our Web Audio coding.

+ +

This pattern can be applied to just about any prefixed JavaScript feature. JavaScript libraries/polyfills also make use of this kind of code, to abstract browser differences away from the developer as much as possible.

+ +

Again, prefixed features were never supposed to be used in production websites — they are subject to change or removal without warning, and cause cross browser issues. If you insist on using prefixed features, make sure you use the right ones. You can look up what browsers require prefixes for different JavaScript/API features on MDN reference pages, and sites like caniuse.com. If you are unsure, you can also find out by doing some testing directly in browsers.

+ +

For example, try going into your browser's developer console and start typing

+ +
window.AudioContext
+ +

If this feature is supported in your browser, it will autocomplete.

+ +

helpを見つける

+ +

There are many other issues you'll encounter with JavaScript; the most important thing to know really is how to find answers online. Consult the HTML and CSS article's Finding help section for our best advice.

+ +

まとめ

+ +

So that's JavaScript. Simple huh? Maybe not so simple, but this article should at least give you a start, and some ideas on how to tackle the JavaScript-related problems you will come across.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS","Learn/Tools_and_testing/Cross_browser_testing/Accessibility", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

 

+ +

このモジュール内

+ + + +

 

diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html new file mode 100644 index 0000000000..297d46d56f --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html @@ -0,0 +1,372 @@ +--- +title: テスト実行のための戦略 +slug: Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies +tags: + - Article + - Automation + - Beginner + - CodingScripting + - Learn + - Testing + - concepts + - cross browser + - device lab + - user testing + - virtual machine +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Introduction","Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

この記事では「(クロス)ブラウザーテストとは何?」「最もよくある問題は何?」「問題をテスト、特定、修正する主な手法は何?」といった質問に答えることで、(クロス)ブラウザーテストの概観を与えることから始めます。

+ + + + + + + + + + + + +
前提条件:HTML, CSS, JavaScript 言語に通じていること; 高レベルのクロスブラウザーテストの原理の理解。
目的:クロスブラウザーテストに含まれる高レベルのコンセプトの理解。
+ +

全部がテスト済み?

+ +

クロスブラウザーテストを実行するとき、ブラウザーのリストを作成する必要があります。ユーザーがあなたのサイトを見る可能性のあるすべてのブラウザーとデバイスの組み合わせをテストする方法はありません — 単に多スすぎるし、新しいものが常に出てきます。

+ +

その代わりに、最も重要なターゲットブラウザー/デバイスを明確にし、それに対して最大限のサポートを広げていくよう守備的にコーディングします。

+ +

守備的にコーディングするとは、ブラウザーで機能やスタイルが動作しない場合に、フォールバックを作るようにすることで、サイトが多少面白みが薄れても受容できるユーザー体験までダウングレードできる — 例えば見た目のすばらしさが失われても、核となる情報にアクセスできることです。

+ +

このねらいは、テスト時に参照できるブラウザー/デバイスの図を作ることです。できるだけ簡単にすることも、できるだけ複雑にすることも、お好みに合わせてできます — 例えば、よくある手法はサポートレベルを次のように複数のグレードに分けることです:

+ +
    +
  1. A グレード: よくある/モダンなブラウザー — 能力のあると知られている。徹底的にテストしてフルサポートを提供する。
  2. +
  3. B グレード: 古い/機能が多くないブラウザー — 能力がないと知られている。基本的な体験をテスト/提供するが、主要な情報やサービスにはするアクセスできるようにする。
  4. +
  5. C グレード: まれな/未知のブラウザー — テストしないが、アクセスを想定する。フルサイトを提供し、少なくとも守備的なコーディングによるフォールバックは動作するようにする。
  6. +
+ +

下記のセクションを通じて、このフォーマットでサポート図を作ります。

+ +
+

: Yahoo は最初にこの手法を、Graded browser Support アプローチとして広めました。

+
+ +

経験則

+ +

これを "仮定"や"感情"と呼ぶかもしれません。これは正確な科学的手法ではありませんが、もウェブ産業の経験のある人にとっては、テストすべきブラウザーについてよくわかるでしょう。サポート図のよい基本となりえます。

+ +

例えば、西ヨーロッパや北アメリカに住んでいる場合、多くが Windows と Mac のデスクトップ/ノートPCを使っていて、主なブラウザーはChrome, Firefox, Safari, IE, Edge です。このブラウザーは定期的な更新があるため、おそらく最初の3つの最新版だけをテストしたいでしょう。Edge と IE では、いくつかの最新バージョンをテストしたくなるでしょう; これらはすべて A グレード区分にすべきでしょう.

+ +
+

: You can only have one version of IE or Edge installed on a machine at once, so you will probably have to use virtual machine, or other strategy to do the testing you need. See {{anch("Virtual machines")}} later on.

+
+ +

多くの人が iOS と Android を使っているので、iOS Safari の最新版、古い Android 内蔵ブラウザーの最新版いくつか、iOS と Android 用の Chrome と Firefox もテストしたくなるでしょう。これらをスマフォとタブレットの両方でテストし、レスポンシブデザインの動作が問題ないのを確認するのが理想でしょう。

+ +

それなりの数の人がまだ IE 9 を使っていることも知っているかもしれません。これは古くて能力もないので、B グレード区分に区分しましょう。

+ +

ここまでで以下のサポート図ができました:

+ +
    +
  1. A グレード: Windows/Mac 用の Chrome と Firefox、Mac 用の Safari、Windows 用の Edge と IE (それぞれ最新の2バージョン)、iPhone/iPad 用の iOS Safari、スマフォ/タブレット用の Android 内蔵ブラウザー (最新2バージョン)、スマフォ/タブレット用の Chrome と Firefox(最新2バージョン)。
  2. +
  3. B グレード: Windows 用 IE 9
  4. +
  5. C グレード: n/a
  6. +
+ +

どこか別の場所に住んでいる場合や、どこか別の場所向けの (例 ある国やロケール)サイトを制作している場合、テストする主なブラウザーはたぶん別のものでしょう。

+ +
+

: "The CEO of my company uses a Blackberry, so we'd better make sure it looks good on that" can also be a persuasive argument.

+
+ +

ブラウザーサポートステータス

+ +

ブラウザーテスト選択で求められる、便利な対策は、ブラウザーサポートステータスです。こんなステータスを提供するサイトはたくさんあります。例えば、:

+ + + +

これらはいずれも北米中心で、正確でないですが、幅広いトレンドの理解を得られます。

+ +

例えば、Netmarketshareを見てみましょう。Opera が少しだが、使用される数が見えるので、Cグレードとしてサポート図に追加するべきでしょう。

+ +

IE8 もある程度ありますが、古くてもはや利用できませんOpera Mini もいくらかありますが、複雑な JavaScript 実行など (詳しくは Opera Mini and JavaScript を見てください)が利用できません。これはグレード B に追加すべきでしょう。

+ +

アクセス解析を使う

+ +

A much more accurate source of data, if you can get it, comes from an analytics app like Google Analytics. This is an application that will give you accurate stats on exactly what browsers people are using to browse your site. Of course, this relies on you already having a site to use it on, so it isn't much good for completely new sites.

+ +

But an analytics history can be useful for finding support stats to influence say a new version of a company's site, or new features you are adding to an existing site. If you have these available, they are far more accurate than global browser stats like those mentioned above.

+ +

You may also consider using open source and privacy focussed analytics platforms like Open Web Analytics and Matomo. They expect you to self-host the analytics platform. 

+ +

Setting up Google analytics

+ +
    +
  1. First of all, you'll need a Google account. Use this account to sign into Google Analytics.
  2. +
  3. Choose the Google Analytics (web) option, and click the Sign Up button.
  4. +
  5. Enter your web site/app details into the signup page. This is fairly intuitive to set up; the most important field to get right is the Website URL. This needs to be your site/app's root URL.
  6. +
  7. Once you've finished filling in everything, press the Get Tracking ID button, then accept the terms of service that appear.
  8. +
  9. The next page provides you with some code snippets and other instructions. For a basic website, what you need to do is copy the Website tracking code block and paste it into all the different pages you want to track using Google Analytics on your site. You could below your closing </body> tag, or somewhere else appropriate that keeps it from getting muddled up with your application code.
  10. +
  11. Upload the changes to the development server, or wherever else you need your code.
  12. +
+ +

That's it! Your site should now be ready to start reporting analytics data.

+ +

Studying analytics data

+ +

Now you should be able to go back to the Analytics Web homepage, and start looking at the data you've collected about your site (you need to leave a little bit of time for some data to actually be collected, of course.)

+ +

既定では, you should see the reporting tab, like so:

+ +

+ +

There is a huge amount of data you could look at using Google Analytics — customized reports in different categories, etc. — and we haven't got time to discuss it all. Getting started with Analytics provides some useful guidance on reporting (and more) for beginners.

+ +

You should also be encouraged to look at the different options on the left hand side, and see what kinds of data you can find out. 例えば、you can find out what browsers and operating systems your users are using by selecting Audience > Technology > Browser & OS from the left hand menu.

+ +
+

: When using Google analytics, you need to beware of misleading bias, e.g. "We  have no Firefox Mobile users" might lead you to not bother supporting Firefox mobile. But you are not going to have any Firefox Mobile users if the site was broken on Firefox mobile in the first place.

+
+ +

その他の考慮

+ +

There are other considerations that you should probably include as well. You should definitely include accessibility as a grade A testing requirement (we'll cover exactly what you should test in our Handling common accessibility problems article)

+ +

Plus you might have other considerations. If you are creating some kind of company intranet for delivering sales figures to managers, and all the managers have been provided with Windows phones 例えば、you might want to make mobile IE support a priority.

+ +

最終的なサポート図

+ +

So, our final support chart will end up looking like so:

+ +
    +
  1. A grade: Chrome and Firefox for Windows/Mac, Safari for Mac, Edge and IE for Windows (last two versions of each), iOS Safari for iPhone/iPad, Android stock browser (last two versions) on phone/tablet, Chrome and Firefox for Android (last two versions) on phone tablet. Accessibility passing common tests.
  2. +
  3. B grade: IE 8 and 9 for Windows, Opera Mini.
  4. +
  5. C grade: Opera, other niche modern browsers.
  6. +
+ +

これから何をテストしていくのか?

+ +

When you've got a new addition to your codebase that needs testing, before you start testing you should write out a list of testing requirements that need to pass to be accepted. These requirements can be visual or functional — both combine to make a usable web site feature.

+ +

Consider the following example (see the source code, and also the example running live):

+ +

+ +

Test criteria for this feature could written like so:

+ +

A and B grade:

+ + + +

A grade:

+ + + +

You may notice from the text in the example that it won't work in IE8 — this is a problem according to our support chart, which you'll have to work on, perhaps by using a feature detection library to implement the functionality in a different way if the browser doesn't support CSS transitions (see Implementing feature detection, later on in the course).

+ +

You might also notice that the button isn't usable using only the keyboard — this also needs to be remedied. Maybe we could use some JavaScript to implement a keyboard control for the toggle, or use some other method entirely?

+ +

These test criteria are useful, because:

+ + + +

Putting together a testing lab

+ +

One option for carrying out browser tests is to do the testing yourself. To do this, you will probably use a combination of actual physical devices, and emulated environments (using either an emulator or a virtual machine).

+ +

物理デバイス

+ +

It is generally better to have a real device running the browser you want to test — this provides the greatest accuracy in terms of behaviour and overall user experience. You'll probably want something like the following, for a reasonable low level device lab:

+ + + +

The following are also good options, if you can get them:

+ + + +

Your main work machine can also be a place to install other tools for specific purposes, such as accessibility auditing tools, screen readers, and emulators/virtual machines.

+ +

Some larger companies have device labs that stock a very large selection of different devices, enabling developers to hunt down bugs on very specific browser/device combinations. Smaller companies and individuals are generally not able to afford such a sophisticated lab, so tend to make do with smaller labs, emulators, virtual machines, and commercial testing apps.

+ +

We will cover each of the other options below.

+ +
+

: Some efforts have been made to create publically accessible device labs — see Open Device Labs.

+
+ +
+

: We also need to consider accessibility — there are a number of useful tools you can install on your machine to facilitate accessibility testing, but we'll cover those in the Handling common accessibility problems article, later in the course.

+
+ +

エミュレーター

+ +

Emulators are basically programs that run inside your computer and emulate a device or particular device conditions of some kind, allowing you to do some of your testing more conveniently than having to find a particular combination of hardware/software to test.

+ +

An emulator might be as simple as testing a device condition. 例えば、if you want to do some quick and dirty testing of your width/height media queries for responsive design, you could use Firefox's Responsive Design Mode. Safari has a similar mode too, which can be enabled by going to Safari > Preferences, and checking Show Develop menu, then choosing Develop > Enter Responsive Design Mode. Chrome also has something similar: Device mode (see Simulate Mobile Devices with Device Mode). 

+ +

More often than not though, you'll have to install some kind of emulator. The most common devices/browsers you'll want to test are as follows:

+ + + +

You can often find simulators for other mobile device environments too, 例えば、:

+ + + +
+

: Many emulators actually require the use of a virtual machine (see below); when this is the case, instructions are often provided, and/or use of the virtual machine is incorporated into the installer of the emulator.

+
+ +

仮想マシン

+ +

Virtual machines are applications that run on your desktop computer and allow you to run emulations of entire operating systems, each compartmentalized in its own virtual hard drive (often represented by a single large file existing on the host machine's hard drive). There are a number of popular virtual machine apps available, such as Parallels, VMWare, and Virtual Box; we personally like the latter, because it is free.

+ +
+

: You need a lot of hard disk space available to run virtual machine emulations; each operating system you emulate can take up a lot of memory. You tend to choose the hard drive space you want for each install; you could get away with probably 10GB, but some sources recommend up to 50GB or more, so the operating system will run reliably. A good option provided by most virtual machine apps is to create a dynamically allocated hard drive that grows and shrinks as the need arises.

+
+ +

To use a Virtual Box, you need to:

+ +
    +
  1. Get hold of an installer disk or image (e.g. ISO file) for the operating system you want to emulate. Virtual Box is unable to provide these; most, like Windows OSes, are commercial products that can't be freely distributed.
  2. +
  3. Download the appropriate installer for your operating system and install it.
  4. +
  5. Open the app; you'll be presented with a view like the following:
  6. +
  7. To create a new virtual machine, press the New button in the top left hand corner.
  8. +
  9. Follow the instructions and fill in the following dialog boxes as appropriate. You'll: +
      +
    1. Provide a name for the new virtual machine
    2. +
    3. Choose with operating system and version you are installing on it
    4. +
    5. Set how much RAM should be allocated (we'd recommend something like 2048MB, or 2GB)
    6. +
    7. Create a virtual hard disk (choose the default options across the three dialog boxes containing Create a virtual hard disk now, VDI (virtual disk image), and Dynamically allocated).
    8. +
    9. Choose the file location and size for the virtual hard disk (choose a sensible name and location to keep it, and for the size specify around 50GB, or as much as you are comfortable with specifying).
    10. +
    +
  10. +
+ +

Now the new virtual box should appear in the left hand menu of the main Virtual Box UI window. At this point, you can double-click to open it — it will start to boot up the virtual machine, but it won't yet have the operating system (OS) installed. At this point you need to point the dialog box at the installer image/disk, and it will run through the steps to install the OS just like on a physical machine.

+ +

+ +
+

Important: You need to make sure you have the operating system image you want to install on the virtual machine available at this point, and install it right away. If you cancel the process at this point, it can render the virtual machine unusable, and make it so you need to delete it and create it again. This is not fatal, but it is annoying.

+
+ +

After the process has completed, you should have a virtual machine running an operating system inside a window on your host computer.

+ +

+ +

You need to treat this virtual operating system installation just like you would any real installation — 例えば、as well as installing the browsers you want to test, install an anti-virus program to protect it from viruses.

+ +

Having multiple virtual machines is very useful, particularly for Windows IE/Edge testing — on Windows, you are not able to have multiple versions of the default browser installed side by side, so you might want to build up a library of virtual machines to handle different tests as required, e.g.:

+ + + +
+

: Another good thing about virtual machines is that the virtual disk images are fairly self-contained. If you are working on a team, you can create one virtual disk image, then copy it and pass it around. Just make sure you have the required licenses to run all those copies of Windows or whatever else you are running, if it is a licensed product.

+
+ +

自動化と商用アプリ

+ +

As mentioned in the last chapter, you can take a lot of the pain out of browser testing by using some kind of automation system. You can set up your own testing automation system (Selenium being the popular app of choice), which does take some setup, but can be very rewarding when you get it worked out.

+ +

There are also commercial tools available such as Sauce Labs and Browser Stack that do this kind of thing for you, without you having to worry about the setup, if you wish to invest some money in your testing.

+ +

We will look at how to use such tools later on in the module.

+ +

ユーザーテスト

+ +

Before we move on, we'll finish this article off by talking a bit about user testing — this can be a good option if you have a willing user group to test your new functionality on. Bear in mind that this can be as lo-fi or as sophisticated as you like — your user group could be a group of friends, a group of colleagues, or a group of unpaid or paid volunteers, depending on whether you have any money to spend on testing.

+ +

Generally you'll get your users to look at the page or view containing the new functionality on some kind of a development server, so you are not putting the final site or change live until it is finished. You should get them to follow some steps and report the results they get. It is useful to provide a set of steps (sometimes called a script) so that you get more reliable results pertaining to what you were trying to test. We mentioned this in the {{anch("What are you going to test")}} section above — it is easy to turn the test criteria detailed there into steps to follow. 例えば、the following would work for a sighted user:

+ + + +

When running tests, it can also be a good idea to:

+ + + +

These steps are designed to make sure that the browser you are testing in is as "pure" as possible, i.e. there is nothing installed that could affect the results of the tests.

+ +
+

: Another useful lo-fi option, if you have the hardware available, is to test your sites on low-end phones/other devices — as sites get larger and feature more effects, there is a higher chance of the site slowing down, so you need to start giving performance more consideration. Trying to get your functionality working on a low end device will make it more likely that the experience will be good on higher-end devices.

+
+ +
+

: Some server-side development environments provide useful mechanisms for rolling out site changes to only a subset of users, providing a useful mechanism for getting a feature tested by a subset of users without the need for a separate development server. An example is Django Waffle Flags.

+
+ +

まとめ

+ +

この記事を読んで、ターゲット顧客/ブラウザーの表を特定して、その表に載っているクロスブラウザーテストを効率的に実行することが良くわかったでしょう。

+ +

次には HTML と CSSから始めて、テストで見つけにくいコードの問題に注目していきましょう。

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Introduction","Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ + + +

このモジュール内

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html new file mode 100644 index 0000000000..ffdd4984a0 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html @@ -0,0 +1,688 @@ +--- +title: テスト自動化環境をセットアップする +slug: Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment +tags: + - Article + - Automation + - Beginner + - Browser + - CodingScripting + - Learn + - Testing + - Tools + - cross browser + - selenium +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

この記事では、Selenium/WebDriver や selenium-webdriver for Node のようなテストライブラリーを使って、自動化環境のインストールとテストを実行する方法を教えます。またあなたのローカルテスト環境と、以前の記事で見てきたような商用アプリとを統合する方法についても見て行きます。

+ + + + + + + + + + + + +
前提条件:HTML, CSSJavaScript のコア機能、principles of cross browser testingautomated testingなどの高レベルのアイデアに精通していること。
目的:Seleniumによるローカルテスト環境のセットアップ方法やSeleniumを使用したテストの実行方法、Sauce LabsやBrowserStackなどのツールとの統合する方法の案内。
+ +

Selenium

+ +

Selenium は最も人気のあるブラウザ自動化ツールです。他の方法もありますが、Selenium を使用する最良の方法は WebDriver を使用することで、強力な API で Selenium 上に構築し、ブラウザを呼び出して自動化し、「このWebページを開く」、「この要素をページ上に移動する」、「このリンクをクリックする」、「リンクがこのURLを開くかどうかを確認する」などといったアクションを実行します。これは、自動テストを実行するのに最適です。
+
+ WebDriverのインストール方法と使用方法は、テストの作成と実行に使用するプログラミング環境によって異なります。最も一般的な環境では、WebDriverとその言語、例えばJava、C#、Ruby、Python、JavaScript(Node)などを使用してWebDriverと通信するのに必要なバインディングをインストールするパッケージまたはフレームワークが利用可能です。異なる言語のSeleniumのセットアップの詳細については、 Setting Up a Selenium-WebDriver Project を参照してください。
+
+ 異なるブラウザでは、WebDriverと通信して制御するために異なるドライバが必要です。ブラウザのドライバの入手先などについては、 Platforms Supported by Selenium を参照してください。
+
+ Node.jsを使用したSeleniumテストの作成と実行については、始める前にすばやく簡単に行うことができ、フロントエンド開発者にはもっと使い慣れた環境を提供する予定です。

+ +
+

: 他のサーバーサイド環境でWebDriverを使用する方法を知りたい場合は、Platforms Supported by Seleniumもチェックしてください。

+
+ +

Node で Selenium のセットアップ

+ +
    +
  1. まず、最後の章の Setting up Node and npm で説明しているように、新しいnpmプロジェクトをセットアップします。selenium-testのように違うものを呼んでください。
  2. +
  3. 次に私たちはNodeの内部からSeleniumが機能するようにフレームワークをインストールする必要があります。 更新頻度が高く、よく改善されるため、私たちはselenium-webdriverを選択します。もしも他の選択をするならばwebdriver.io と nightwatch.js もいい選択です。selenium-webdriverをインストールするため, プロジェクトフォルダの下で以下のコマンドを走らせます:
  4. +
  5. +
    npm install selenium-webdriver
    +
  6. +
+ +
+

: 以前に selenium-webdriver をインストールしてブラウザドライバをダウンロードした場合でも、これらの手順を実行することをお勧めします。すべてが最新であることを確認する必要があります。

+
+ +

Next, you need to download the relevant drivers to allow WebDriver to control the browsers you want to test. You can find details of where to get them from on the selenium-webdriver page (see the table in the first section.) Obviously, some of the browsers are OS-specific, but we're going to stick with Firefox and Chrome, as they are available across all the main OSes.

+ +
    +
  1. Download the latest GeckoDriver (for Firefox) and ChromeDriver drivers.
  2. +
  3. Unpack them into somewhere fairly easy to navigate to, like the root of your home user directory.
  4. +
  5. Add the chromedriver and geckodriver driver's location to your system PATH variable. This should be an absolute path from the root of your hard disk, to the directory containing the drivers. 例えば、if we were using a Mac OS X machine, our user name was bob, and we put our drivers in the root of our home folder, the path would be /Users/bob.
  6. +
+ +
+

: Just to reiterate, the path you add to PATH needs to be the path to the directory containing the drivers, not the paths to the drivers themselves! This is a common mistake.

+
+ +

To set your PATH variable on Mac OS X/most Linux systems:

+ +
    +
  1. Open your .bash_profile (or .bashrc) file (if you can't see hidden files, you'll need to display them, see Show/Hide hidden files in Mac OS X or Show hidden folders in Ubuntu).
  2. +
  3. Paste the following into the bottom of your file (updating the path as it actually is on your machine): +
    #Add WebDriver browser drivers to PATH
    +
    +export PATH=$PATH:/Users/bob
    +
  4. +
  5. Save and close this file, then restart your Terminal/command prompt to reapply your Bash configuration.
  6. +
  7. Check that your new paths are in the PATH variable by entering the following into your terminal: +
    echo $PATH
    +
  8. +
  9. You should see it printed out in the terminal.
  10. +
+ +

To set your PATH variable on Windows, follow the instructions at How can I add a new folder to my system path?

+ +

OK, let's try a quick test to make sure everything is working.

+ +
    +
  1. Create a new file inside your project directory called google_test.js:
  2. +
  3. Give it the following contents, then save it: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until;
    +
    +var driver = new webdriver.Builder()
    +    .forBrowser('firefox')
    +    .build();
    +
    +driver.get('http://www.google.com');
    +
    +driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +driver.sleep(1000).then(function() {
    +  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +});
    +
    +driver.findElement(By.name('btnK')).click();
    +
    +driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +    } else {
    +      console.log('Test failed');
    +    }
    +  });
    +});
    +
    +driver.quit();
    +
  4. +
  5. In terminal, make sure you are inside your project folder, then enter the following command: +
    node google_test
    +
  6. +
+ +

You should see an instance of Firefox automatically open up! Google should automatically be loaded in a tab, "webdriver" should be entered in the search box, and the search button will be clicked. WebDriver will then wait for 2 seconds; the document title is then accessed, and if it is "webdriver - Google Search", we will return a message to claim the test is passed. WebDriver will then close down the Firefox instance and stop.

+ +

一度に複数ブラウザでテストする

+ +

There is also nothing to stop you running the test on multiple browsers simulataneously. Let's try this!

+ +
    +
  1. Create another new file inside your project directory called google_test_multiple.js. You can feel free to change the references to some of the other browsers we added, remove them, etc., depending on what browsers you have available to test on your operating system. You'll need to make sure you have the right browser drivers set up on your system. In terms of what string to use inside the .forBrowser() method for other browsers,  see the Browser enum reference page.
  2. +
  3. Give it the following contents, then save it: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until;
    +
    +var driver_fx = new webdriver.Builder()
    +    .forBrowser('firefox')
    +    .build();
    +
    +var driver_chr = new webdriver.Builder()
    +    .forBrowser('chrome')
    +    .build();
    +
    +searchTest(driver_fx);
    +searchTest(driver_chr);
    +
    +function searchTest(driver) {
    +  driver.get('http://www.google.com');
    +  driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +  driver.sleep(1000).then(function() {
    +    driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +  });
    +
    +  driver.findElement(By.name('btnK')).click();
    +
    +  driver.sleep(2000).then(function() {
    +    driver.getTitle().then(function(title) {
    +      if(title === 'webdriver - Google Search') {
    +        console.log('Test passed');
    +      } else {
    +        console.log('Test failed');
    +      }
    +    });
    +  });
    +
    +  driver.quit();
    +}
    +
  4. +
  5. In terminal, make sure you are inside your project folder, then enter the following command: +
    node google_test_multiple
    +
  6. +
  7. If you are using a Mac and do decide to test Safari, you might get an error message along the lines of "Could not create a session: You must enable the 'Allow Remote Automation' option in Safari's Develop menu to control Safari via WebDriver." If you get this, follow the given instruction and try again.
  8. +
+ +

So here we've done the test as before, except that this time we've wrapped it inside a function, searchTest(). We've created new browser instances for multiple browsers, then passed each one to the function so the test is performed on all three browsers!

+ +

Fun huh? Let's move on, look at the basics of WebDriver syntax, in a bit more detail.

+ +

WebDriver 構文クラッシュコース

+ +

Let's have a look at a few key features of the webdriver syntax. For more complete details, you should consult the selenium-webdriver JavaScript API reference for a detailed reference, and the Selenium main documentation's Selenium WebDriver and WebDriver: Advanced Usage pages, which contain multiple examples to learn from written in different languages.

+ +

新しいテストを始める

+ +

To start up a new test, you need to include the selenium-webdriver module like this:

+ +
var webdriver = require('selenium-webdriver'),
+    By = webdriver.By,
+    until = webdriver.until;
+ +

Next, you need to create a new instance of a driver, using the new webdriver.Builder() constructor. This needs to have the forBrowser() method chained onto it to specify what browser you want to test with this builder, and the build() method to actually build it (see the Builder class reference for detailed information on these features).

+ +
var driver = new webdriver.Builder()
+    .forBrowser('firefox')
+    .build();
+ +

Note that it is possible to set specific configuration options for browsers to be tested, 例えば、you can set a specific version and OS to test in the forBrowser() method:

+ +
var driver = new webdriver.Builder()
+    .forBrowser('firefox', '46', 'MAC')
+    .build();
+ +

You could also set these options using an environment variable, 例えば、:

+ +
SELENIUM_BROWSER=firefox:46:MAC
+ +

Let's create a new test to allow us to explore this code as we talk about it. Inside your selenium test project directory, create a new file called quick_test.js, and add the following code to it:

+ +
var webdriver = require('selenium-webdriver'),
+    By = webdriver.By,
+    until = webdriver.until;
+
+var driver = new webdriver.Builder()
+    .forBrowser('firefox')
+    .build();
+ +

テストするドキュメントの取得

+ +

To load the page you actually want to test, you use the get() method of the driver instance you created earlier, 例えば、:

+ +
driver.get('http://www.google.com');
+ +
+

: See the WebDriver class reference for details of the features in this section and the ones below it.

+
+ +

You can use any URL to point to your resource, including a file:// URL to test a local document:

+ +
driver.get('file:///Users/chrismills/git/learning-area/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html');
+ +

or

+ +
driver.get('http://localhost:8888/fake-div-buttons.html');
+ +

But it is better to use a remote server location so the code is more flexible — when you start using a remote server to run your tests (see later on), your code will break if you try to use local paths. 

+ +

Add this line to the bottom of quick_test.js now:

+ +
driver.get('http://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html');
+ +

文書とのやりとり

+ +

Now we've got a document to test, we need to interact with it in some way, which usually involves first selecting a specific element to test something about. You can select UI elements in many ways in WebDriver, including by ID, class, element name, etc. The actual selection is done by the findElement() method, which accepts as a parameter a selection method. 例えば、to select an element by ID:

+ +
var element = driver.findElement(By.id('myElementId'));
+ +

One of the most useful ways to find an element by CSS — the  By.css method allows you to select an element using a CSS selector

+ +

Enter the following at the bottom of your quick_test.js code now:

+ +
var button = driver.findElement(By.css('button:nth-of-type(1)'));
+ +

要素のテスト

+ +

There are many ways to interact with your web documents and elements on them. You can see useful common examples starting at Getting text values on the WebDriver docs.

+ +

If we wanted to get the text inside our button, we could do this:

+ +
button.getText().then(function(text) {
+  console.log('Button text is \'' + text + '\'');
+});
+ +

Add this to quick_test.js now.

+ +

Making sure you are inside your project directory, try running the test:

+ +
node quick_test.js
+ +

You should see the button's text label reported inside the console.

+ +

let's do something a bit more useful. delete the previous code entry, then add this line at the bottom instead:

+ +
button.click();
+ +

Try running your test again; the button will be clicked, and the alert() popup should appear. At least we know the button is working!

+ +

You can interact with the popup too. Add the following to the bottom of the code, and try testing it again:

+ +
var alert = driver.switchTo().alert();
+
+alert.getText().then(function(text) {
+  console.log('Alert text is \'' + text + '\'');
+});
+
+alert.accept();
+ +

Next, let's try entering some text into one of the form elements. Add the following code and try running your test again:

+ +
var input = driver.findElement(By.id('input1'));
+input.sendKeys('Filling in my form');
+ +

You can submit key presses that can't be represented by normal characters using properties of the webdriver.Key object. 例えば、above we used this construct to tab out of the form input before submitting it:

+ +
driver.sleep(1000).then(function() {
+  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
+});
+
+ +

何かが完了するのを待つ

+ +

There are times where you'll want to make WebDriver wait for something to complete before carrying on. 例えば、if you load a new page, you'll want to wait for the page's DOM to finish loading before you try to interact with any of its elements, otherwise the test will likely fail.

+ +

In our google_test.js test 例えば、we included this block:

+ +
driver.sleep(2000).then(function() {
+  driver.getTitle().then(function(title) {
+    if(title === 'webdriver - Google Search') {
+      console.log('Test passed');
+    } else {
+      console.log('Test failed');
+    }
+  });
+});
+ +

The sleep() method accepts a value that specifies the time to wait in milliseconds — the method returns a promise that resolves at the end of that time, at which point the code inside the then() executes. In this case we get the title of the current page with the getTitle() method, then return a pass or fail message depending on what its value is.

+ +

We could add a sleep() method to our quick_test.js test too — try wrapping your last line of code in a block like this:

+ +
driver.sleep(2000).then(function() {
+  input.sendKeys('Filling in my form');
+  input.getAttribute("value").then(function(value) {
+    if(value !== '') {
+      console.log('Form input editable');
+    }
+  });
+});
+ +

WebDriver will now wait for 2 seconds before filling in the form field. We then test whether its value got filled in (i.e. is not empty) by using getAttribute() to retrieve it's value attribute value, and print a message to the console if it is not empty.

+ +
+

: There is also a method called wait(), which repeatedly tests a condition for a certain length of time, and then carries on executing the code. This also makes use of the util library, which defines common conditions to use along with wait().

+
+ +

使用後のドライバのシャットダウン

+ +

After you've finished running a test, you should shut down any dirver instances you've opened, to make sure that you don't end up with loads of rogue browser instances open on your machine! This is done using the quit() method. Simply call this on your driver instance when you are finished with it. Add this line to the bottom of your quick_test.js test now:

+ +
driver.quit();
+ +

When you run it, you should now see the test execute and the browser instance shut down again after the text is complete. This is useful for not cluttering up your computer with loads of browser instances, especially if you have so many that it is causing the computer to slow down.

+ +

テストのベストプラクティス

+ +

There has been a lot written about best practices for writing tests. You can find some good background information at Test Design Considerations. In general, you should make sure that your tests are:

+ +
    +
  1. Using good locator strategies: When you are {{anch("Interacting with the document")}}, make sure that you use locators and page objects that are unlikely to change — if you have a testable element that you want to perform a test on, make sure that it has a stable ID, or position on the page that can be selected using a CSS selector, which isn't going to just change with the next site iteration. You want to make your tests as non-brittle as possible, i.e. they won't just break when something changes.
  2. +
  3. Write atomic tests: Each test should test one thing only, making it easy to keep track of what test file is testing which criterion. As an example, the google_test.js test we looked at above is pretty good, as it just tests a single thing — whether the title of a search results page is set correctly. We could work on giving it a better name so it is easier to work out what it does if we add more google tests. Perhaps results_page_title_set_correctly.js would be slightly better?
  4. +
  5. Write autonomous tests: Each test should work on it's own, and not depend on other tests to work.
  6. +
+ +

In addition, we should mention test results/reporting — we've been reporting results in our above examples using simple console.log() statements, but this is all done in JavaScript, so you can use whatever test running and resorting system you want, be it Mocha/Chai/some other kind of combination.

+ +
    +
  1. 例えば、try making a local copy of our mocha_test.js example inside your project directory. Put it inside a subfolder called test. This example uses a long chain of promises to run all the steps required in our test — the promise-based methods WebDriver uses need to resolve for it to work properly.
  2. +
  3. Install the mocha test harness by running the following command inside your project directory: +
    npm install --save-dev mocha
    +
  4. +
  5. you can now run the test (and any others you put inside your test directory) using the following command: +
    mocha --no-timeouts
    +
  6. +
  7. You should include the --no-timeouts flag to make sure your tests don't end up failing because of Mocha's arbitrary timeout (which is 3 seconds).
  8. +
+ +
+

: saucelabs-sample-test-frameworks contains several useful examples showing how to set up different combinations of test/assertion tools.

+
+ +

リモートテストの実行

+ +

It turns out that running tests on remote servers isn't that much more difficult than running them locally. You just need to create your driver instance, but with a few more features specified, including the capabilities of the browser you want to test on, the address of the server, and the user credentials you need (if any) to access it.

+ +

BrowserStack

+ +

Getting Selenium tests to run remotely on BrowserStack is easy. The code you need should follow the pattern seen below.

+ +

Let's write an example:

+ +
    +
  1. Inside your project directory, create a new file called bstack_google_test.js.
  2. +
  3. Give it the following contents: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until;
    +
    +// Input capabilities
    +var capabilities = {
    +   'browserName' : 'Firefox',
    +   'browser_version' : '56.0 beta',
    +   'os' : 'OS X',
    +   'os_version' : 'Sierra',
    +   'resolution' : '1280x1024',
    +   'browserstack.user' : 'YOUR-USER-NAME',
    +   'browserstack.key' : 'YOUR-ACCESS-KEY',
    +   'browserstack.debug' : 'true',
    +   'build' : 'First build'
    +};
    +
    +var driver = new webdriver.Builder().
    +  usingServer('http://hub-cloud.browserstack.com/wd/hub').
    +  withCapabilities(capabilities).
    +  build();
    +
    +driver.get('http://www.google.com');
    +driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +driver.sleep(1000).then(function() {
    +  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +});
    +
    +driver.findElement(By.name('btnK')).click();
    +
    +driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +    } else {
    +      console.log('Test failed');
    +    }
    +  });
    +});
    +
    +driver.quit();
    +
  4. +
  5. From your BrowserStack automation dashboard, get your user name and access key (see Username and Access Keys). Replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (and make sure you keep them secure).
  6. +
  7. Run your test with the following command: +
    node bstack_google_test
    + The test will be sent to BrowserStack, and the test result will be returned to your console. This shows the importance of including some kind of result reporting mechanism!
  8. +
  9. Now if you go back to the BrowserStack automation dashboard page, you'll see your test listed:
    +
  10. +
+ +

If you click on the link for your test, you'll get to a new screen where you will be able to see a video recording of the test, and multiple detailed logs of information pertaining to it.

+ +
+

: The Resources menu option on the Browserstack automation dashboard contains a wealth of useful information on using it to run automated tests. See Node JS Documentation for writing automate test scripts in Node JS for the node-specific information. Expore the docs to find out all the useful things BrowserStack can do.

+
+ +
+

: If you don't want to write out the capabilities objects for your tests by hand, you can generate them using the generators embedded in the docs. See Run tests on mobile browsers and Run tests on desktop browsers.

+
+ +

プログラムによるBrowserStackテストの詳細の入力

+ +

You can use the BrowserStack REST API and some other capabilities to annotate your test with more details, such as whether it passed, why it passed, what project the test is part of, etc. BrowserStack doesn't know these details 既定では!

+ +

Let's update our bstack_google_test.js demo, to show how these features work:

+ +
    +
  1. First, we 'll need to import the node request module, so we can use it to send requests to the REST API. Add the following line at the very top of your code: +
    var request = require("request");
    +
  2. +
  3. Now we'll update our capabilities object to include a project name — add the following line before the closing curly brace, remembering to add a comma at the end of the previous line (you can vary the build and project names to organize the tests in different windows in the BrowserStack automation dashboard): +
    'project' : 'Google test 2'
    +
  4. +
  5. Next we need to access the sessionId of the current session, so we know where to send the request (the ID is included in the request URL, as you'll see later). Include the following lines just below the block that creates the driver object (var driver ...) : +
    var sessionId;
    +
    +driver.session_.then(function(sessionData) {
    +    sessionId = sessionData.id_;
    +});
    +
  6. +
  7. Finally, update the driver.sleep(2000) ... block near the bottom of the code to add REST API calls (again, replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values): +
    driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +      request({uri: "https://YOUR-USER-NAME:YOUR-ACCESS-KEY@www.browserstack.com/automate/sessions/" + sessionId + ".json", method:"PUT", form:{"status":"passed","reason":"Google results showed correct title"}});
    +    } else {
    +      console.log('Test failed');
    +      request({uri: "https://YOUR-USER-NAME:YOUR-ACCESS-KEY@www.browserstack.com/automate/sessions/" + sessionId + ".json", method:"PUT", form:{"status":"failed","reason":"Google results showed wrong title"}});
    +    }
    +  });
    +});
    +
  8. +
+ +

These are fairly intuitive — once the test completes, we send an API call to BrowserStack to update the test with a passed or failed status, and a reason for the result.

+ +

If you now go back to your BrowserStack automation dashboard page, you should see your test session available, as before, but with the updated data attached to it:

+ +

+ +

Sauce Labs

+ +

Getting Selenium tests to run remotely on Sauce Labs is also very simple, and very similar to BrowserStack albeit with a few syntactic differences. The code you need should follow the pattern seen below.

+ +

Let's write an example:

+ +
    +
  1. Inside your project directory, create a new file called sauce_google_test.js.
  2. +
  3. Give it the following contents: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until,
    +    username = "YOUR-USER-NAME",
    +    accessKey = "YOUR-ACCESS-KEY";
    +
    +var driver = new webdriver.Builder()
    +    .withCapabilities({
    +      'browserName': 'chrome',
    +      'platform': 'Windows XP',
    +      'version': '43.0',
    +      'username': username,
    +      'accessKey': accessKey
    +    })
    +    .usingServer("https://" + username + ":" + accessKey +
    +          "@ondemand.saucelabs.com:443/wd/hub")
    +    .build();
    +
    +driver.get('http://www.google.com');
    +
    +driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +driver.sleep(1000).then(function() {
    +  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +});
    +
    +driver.findElement(By.name('btnK')).click();
    +
    +driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +    } else {
    +      console.log('Test failed');
    +    }
    +  });
    +});
    +
    +driver.quit();
    +
  4. +
  5. From your Sauce Labs user settings, get your user name and access key. Replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (and make sure you keep them secure).
  6. +
  7. Run your test with the following command: +
    node sauce_google_test
    + The test will be sent to Sauce Labs, and the test result will be returned to your console. This shows the importance of including some kind of result reporting mechanism!
  8. +
  9. Now if you go to your Sauce Labs Automated Test dashboard page, you'll see your test listed; from here you'll be able to see videos, screenshots, and other such data.
    +
  10. +
+ +
+

: Sauce Labs' Platform Configurator is a useful tool for generating capability objects to feed to your driver instances, based on what browser/OS you want to test on.

+
+ +
+

: for more useful details on testing with Sauce Labs and Selenium, check out Getting Started with Selenium for Automated Website Testing, and Instant Selenium Node.js Tests.

+
+ +

Sauce Labsテストの詳細をプログラムで書き込む

+ +

You can use the Sauce Labs API to annotate your test with more details, such as whether it passed, the name of the test, etc. Sauce Labs doesn't know these details 既定では!

+ +

To do this, you need to:

+ +
    +
  1. Install the Node Sauce Labs wrapper using the following command (if you've not already done it for this project): +
    npm install saucelabs --save-dev
    +
  2. +
  3. Require saucelabs — put this at the top of your sauce_google_test.js file, just below the previous variable declarations: +
    var SauceLabs = require('saucelabs');
    +
  4. +
  5. Create a new instance of SauceLabs, by adding the following just below that: +
    var saucelabs = new SauceLabs({
    +    username : "YOUR-USER-NAME",
    +    password : "YOUR-ACCESS-KEY"
    +});
    + Again, replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (note that the saucelabs npm package rather confusingly uses password, not accessKey). Since you are using these twice now, you may want to create a couple of helper variables to store them in.
  6. +
  7. Below the block where you define the driver variable (just below the build() line), add the following block — this gets the correct driver sessionID that we need to write data to the job (you can see it action in the next code block): +
    driver.getSession().then(function (sessionid){
    +      driver.sessionID = sessionid.id_;
    +});
    +
  8. +
  9. Finally, replace the driver.sleep(2000) ... block near the bottom of the code with the following: +
    driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +      var testPassed = true;
    +    } else {
    +      console.log('Test failed');
    +      var testPassed = false;
    +    }
    +
    +    saucelabs.updateJob(driver.sessionID, {
    +      name: 'Google search results page title test',
    +      passed: testPassed
    +    });
    +  });
    +});
    +
  10. +
+ +

Here we've set a testPassed variable to true or false depending on whether the test passed or fails, then we've used the saucelabs.updateJob() method to update the details.

+ +

If you now go back to your Sauce Labs Automated Test dashboard page, you should see your new job now has the updated data attached to it:

+ +

+ +

自身のリモートサーバ

+ +

If you don't want to use a service like Sauce Labs or BrowserStack, you can always set up your own remote testing server. Let's look at how to do this.

+ +
    +
  1. The Selenium remote server requires Java to run. Download the latest JDK for your platform from the Java SE downloads page. Install it when it is downloaded.
  2. +
  3. Next, download the latest Selenium standalone server — this acts as a proxy between your script and the browser drivers. Choose the latest stable version number (i.e. not a beta), and from the list choose a file starting with "selenium-server-standalone". When this has downloaded, put it in a sensible place, like in your home directory. If you've not already added the location to your PATH, do so now (see the {{anch("Setting up Selenium in Node")}} section).
  4. +
  5. Run the standalone server by entering the following into a terminal on your server computer +
    java -jar selenium-server-standalone-3.0.0.jar
    + (update the .jar filename) so it matches exactly what file you've got.
  6. +
  7. The server will run on http://localhost:4444/wd/hub — try going there now to see what you get.
  8. +
+ +

Now we've got the server running, let's create a demo test that will run on the remote selenium server.

+ +
    +
  1. Create a copy of your google_test.js file, and call it google_test_remote.js; put it in your project directory.
  2. +
  3. Update the second code block (which starts with var driver = ) like so +
    var driver = new webdriver.Builder()
    +    .forBrowser('firefox')
    +    .usingServer('http://localhost:4444/wd/hub')
    +    .build();
    +
  4. +
  5. Run your test, and you should see it run as expected; this time however you will be runing it on the standalone server: +
    node google_test_remote.js
    +
  6. +
+ +

So this is pretty cool. We have tested this locally, but you could set this up on just about any server along with the relevant browser drivers, and then connect your scripts to it using the URL you choose to expose it at.

+ +

selenium と CI ツールのインテグレーション

+ +

As another point, it is also possible to integrate Selenium and related tools like Sauce Labs with continuous integration (CI) tools — this is useful, as it means you can run your tests via a CI tool, and only commit new changes to your code repository if the tests pass.

+ +

It is out of scope to look at this area in detail in this article, but we'd suggest getting started with Travis CI — this is probably the easiest CI tool to get started with, and has good integration with web tools like GitHub and Node.

+ +

To get started, see 例えば、:

+ + + +

まとめ

+ +

This module should have proven fun, and should have given you enough of an insight into writing and running automated tests for you to get going with writing your own automated tests.

+ +

{{PreviousMenu("Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ + + +

このモジュール内

+ + + + + + + + + +
+ +
+

...

+
diff --git a/files/ja/learn/tools_and_testing/index.html b/files/ja/learn/tools_and_testing/index.html new file mode 100644 index 0000000000..152ebc54eb --- /dev/null +++ b/files/ja/learn/tools_and_testing/index.html @@ -0,0 +1,49 @@ +--- +title: ツールとテスト +slug: Learn/Tools_and_testing +tags: + - CSS + - CodingScripting + - HTML + - JavaScript + - Landing + - TopicStub + - user testing + - アクセシビリティ + - クロスブラウザ + - ツール + - テスト + - トピック + - 初心者 + - 学習 + - 自動化 +translation_of: Learn/Tools_and_testing +--- +
{{LearnSidebar}}
+ +

ウェブ技術のコア (HTML, CSS,  JavaScript のような) での快適なプログラミングを開始して、経験を積んで、色んなリソースを読み、色んなコツや技を学習すると、JavaScript フレームワークからテスト自動化ツールやそれ以外まで、すべてのツールに出くわします。ウェブプロジェクトが大きく複雑になっていくと、こうしたツールを活用したり、コードの信頼できるテスト計画を考案したくなるでしょう。

+ +

さらに、クロスブラウザーのサポートを引き続き維持することを念頭に置き、ユーザーのウェブブラウジングに使用されているさまざまなブラウザーやデバイス間でプロジェクトを動作させるベストプラクティスに従う必要があります。そして障害を持つ人々が利用できるようにすることです。

+ +

あなたが使用すべきツールを考え出すことは難しい処理でありえるため、私たちは一連の記事を書いて、利用可能なツールの種類、あなたのためにできること、現在の業界のお気に入りを利用する方法をお伝えします。

+ +
+

メモ: このトピックでは多数のツールを参照していますが、必ずしもこれらのツールを最良または唯一の方法として推奨しているわけではなく、動作していてサポートしているためです。ほとんどの場合、他にも方法がありますが、古いものは時代遅れで、間違いなく新しいものが出てきます。

+
+ +

学習経路

+ +

ここで説明したツールを使用する前にまずベースとなる HTMLCSS、および JavaScript 言語の基本を最初に理解しておく必要があります。たとえば、複雑な Web コードで問題をデバッグしたり、JavaScript フレームワークを効果的に使用したり、テストランナーなどを使用してコードをテストして実行したりする前に、これらの言語の基礎を知る必要があります。

+ +

それに加えて、このトピックの最初のモジュールから始めて、そこでエリア全体の便利な概観を得るべきでしょう。

+ +

モジュール

+ +
+
クライアント側ウェブ開発ツールの理解
+
クライアント側のツールには脅威を感じますが、この記事シリーズではいくつかの普遍的なクライアント側のツール種類ごとに目的を例示して、一緒に連携させるツールや、パッケージマネージャーを使ったインストール方法、コマンドラインでの制御を説明します。最後にツールチェーンの例と、どのように生産的になるのかを示します。
+
Git と GitHub
+
開発者はいくつかの バージョン管理システム (VCS)を使い、このツールにてプロジェクトの他の開発者と、お互いの成果を上書きする危険なく、後に問題が見つかった場合前バージョンのコードベースにロールバックできます。最も人気のある VCS (少なくともウェブ開発では) は Git と、それで動作するリポジトリとツールをホストするサイトの GitHub です。このモジュールではその両方について知っておくべきことを教えます。
+
クロスブラウザーテスト
+
このモジュールではさまざまなブラウザー間でウェブプロジェクトをテストする領域を具体的に示しています。ここでは、ターゲットとするユーザー層 (たとえばユーザー、ブラウザー、デバイスの中で最も心配する必要があるもの)、テストの方法、さまざまな種類のコードで直面する主な問題、問題をテストして解決するのに最も有用なツールと、テストをスピードアップするために自動化する方法について説明します。
+
-- cgit v1.2.3-54-g00ecf