├── lib └── requirements.txt ├── .gitignore ├── book ├── chapters │ └── introduction.tex └── main.tex ├── Makefile ├── README.md ├── outline.md └── vendor └── minted.sty /lib/requirements.txt: -------------------------------------------------------------------------------- 1 | Pygments==1.6 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.dvi 3 | *.aux 4 | *.log 5 | *.pyg 6 | -------------------------------------------------------------------------------- /book/chapters/introduction.tex: -------------------------------------------------------------------------------- 1 | \chapter{Introduction} 2 | 3 | This is a fake introduction. 4 | -------------------------------------------------------------------------------- /book/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass{book} 2 | \usepackage{import} 3 | \usepackage{../vendor/minted} 4 | \begin{document} 5 | 6 | \title{Appium: Mobile Automation Made Awesome} 7 | \author{Jonathan Lipps} 8 | \maketitle 9 | 10 | \subimport{chapters/}{introduction.tex} 11 | 12 | \end{document} 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEFAULT: 2 | make clean && make build 3 | 4 | build: 5 | mkdir -p build 6 | cd book && \ 7 | pdflatex -shell-escape main.tex && \ 8 | mv main.pdf ../build/book.pdf 9 | 10 | clean: 11 | rm -rf build/ 12 | rm -rf book/*.log 13 | rm -rf book/*.aux 14 | rm -rf book/*.pdf 15 | rm -rf book/*.pyg 16 | 17 | .PHONY: \ 18 | DEFAULT \ 19 | build \ 20 | clean 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Appium Book 2 | ===== 3 | 4 | This is the public repository for my forthcoming Appium book, tentatively 5 | titled *Appium: Mobile Automation Made Awesome*. I'm writing/developing the 6 | book here on GitHub so that anyone can read it, track its progress, clone the 7 | repo, and create their own PDF versions of the book for their own personal use. 8 | 9 | ## The Story 10 | 11 | Appium is an open-source project, and so I felt the first major book about 12 | Appium should be written in the open. I'm accepting pull requests for fixes or 13 | suggested modifications to the book, and the authors of the pull requests 14 | I merge will be listed as contributors to the book in the final version. (I am 15 | retaining copyright for the book, and contributors will be asked to sign a CLA 16 | to that effect). 17 | 18 | The source for the book will always be here, so that anyone can build the book 19 | for themselves. However, distribution of the compiled PDF, or of modified 20 | source for the book, is prohibited without written permission from me. I will 21 | release a free version of the PDF for the first revision of the book as a gift 22 | to the Appium community. Hard-copy versions and updated revisions of the book 23 | will be available for purchase (details TBD). 24 | 25 | ## The Content 26 | 27 | Check out [the outline](outline.md) to see the work-in-progress plan for what 28 | kinds of information the book will include. 29 | 30 | ## Building the book 31 | 32 | Here are the instructions for turning the source into a PDF you can read. 33 | 34 | ### System/Project Setup 35 | 36 | 0. Install a [TeX Live](https://tug.org/mactex/) distribution of some kind, 37 | e.g.: 38 | ``` 39 | brew cask install mactex 40 | ``` 41 | 0. Get a Python virtualenv or use your system env, and install deps: 42 | ``` 43 | pip install -r lib/requirements.txt 44 | ``` 45 | 46 | ### Build Instructions 47 | 48 | 0. Run `make` 49 | 0. Look inside the `build/` directory for `book.pdf` 50 | -------------------------------------------------------------------------------- /outline.md: -------------------------------------------------------------------------------- 1 | Book Outline 2 | ===== 3 | 4 | 0. Foreword 5 | 0. Introduction 6 | 0. What is Appium? 7 | 0. Core concepts for the book 8 | 0. Automation 9 | 0. Test automation 10 | 0. Mobile SDKs 11 | 0. Selenium WebDriver 12 | 0. Why Appium? 13 | 0. Philosophy 14 | 0. Alternatives 15 | 0. History of Selenium 16 | 0. RC 17 | 0. WebDriver and the JSON Wire Protocol 18 | 0. The WebDriver W3C Spec 19 | 0. History of Appium 20 | 0. The Need for Mobile Automation 21 | 0. Dan Cuellar: The Hack 22 | 0. Mobile Testing Summit 2012 23 | 0. Jason Huggins: Sauce Labs Shows Interest 24 | 0. Rearchitecting as a Node.js Server 25 | 0. The Road to 1.0 26 | 0. Important Conceptual Background 27 | 0. Types of Mobile Applications 28 | 0. Native 29 | 0. Hybrid 30 | 0. Mobile Web 31 | 0. HTTP Servers and REST APIs 32 | 0. HTTP Client Libraries 33 | 0. Selenium Clients and Appium Clients 34 | 0. The JSON Wire Protocol vs the WebDriver W3C Background 35 | 0. Selenium/Appium Sessions 36 | 0. Desired Capabilities 37 | 0. Architecture of Appium 38 | 0. Appium as a Protocol Gateway 39 | 0. Appium as Cross-Platform Glue 40 | 0. Appium as Boilerplate Removal 41 | 0. Vendor-provided Automation Frameworks 42 | 0. iOS UIAutomation 43 | 0. Android UiAutomator 44 | 0. Android Instrumentation (via Selendroid) 45 | 0. FirefoxOS Marionette 46 | 0. General Server Architecture 47 | 0. Native Automation Architectures 48 | 0. iOS 49 | 0. Android (Appium Native) 50 | 0. Android (Selendroid) 51 | 0. FirefoxOS 52 | 0. Hybrid Automation Architectures 53 | 0. iOS 54 | 0. Android (Appium Native) 55 | 0. Android (Selendroid) 56 | 0. FirefoxOS 57 | 0. Mobile Web Automation Architectures 58 | 0. iOS 59 | 0. Android (ChromeDriver) 60 | 0. FirefoxOS 61 | 0. Getting set up 62 | 0. Mobile SDKs 63 | 0. Android 64 | 0. iOS 65 | 0. FirefoxOS 66 | 0. Platforms 67 | 0. Mac 68 | 0. Linux 69 | 0. Windows 70 | 0. Appium 71 | 0. NPM 72 | 0. GUI 73 | 0. Source 74 | 0. To be continued... 75 | -------------------------------------------------------------------------------- /vendor/minted.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `minted.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% minted.dtx (with options: `package') 8 | %% Copyright 2010--2011 Konrad Rudolph 9 | %% 10 | %% This work may be distributed and/or modified under the 11 | %% conditions of the LaTeX Project Public License, either version 1.3 12 | %% of this license or (at your option) any later version. 13 | %% The latest version of this license is in 14 | %% http://www.latex-project.org/lppl.txt 15 | %% and version 1.3 or later is part of all distributions of LaTeX 16 | %% version 2005/12/01 or later. 17 | %% 18 | %% Additionally, the project may be distributed under the terms of the new BSD 19 | %% license. 20 | %% 21 | %% This work has the LPPL maintenance status `maintained'. 22 | %% 23 | %% The Current Maintainer of this work is Konrad Rudolph. 24 | %% 25 | %% This work consists of the files minted.dtx and minted.ins 26 | %% and the derived file minted.sty. 27 | \NeedsTeXFormat{LaTeX2e} 28 | \ProvidesPackage{minted}[2011/09/17 v1.7 Yet another Pygments shim for LaTeX] 29 | \RequirePackage{keyval} 30 | \RequirePackage{fancyvrb} 31 | \RequirePackage{xcolor} 32 | \RequirePackage{float} 33 | \RequirePackage{ifthen} 34 | \RequirePackage{calc} 35 | \RequirePackage{ifplatform} 36 | \DeclareOption{chapter}{\def\minted@float@within{chapter}} 37 | \DeclareOption{section}{\def\minted@float@within{section}} 38 | \ProcessOptions\relax 39 | \ifwindows 40 | \providecommand\DeleteFile[1]{\immediate\write18{del #1}} 41 | \else 42 | \providecommand\DeleteFile[1]{\immediate\write18{rm #1}} 43 | \fi 44 | \newboolean{AppExists} 45 | \newcommand\TestAppExists[1]{ 46 | \ifwindows 47 | \DeleteFile{\jobname.aex} 48 | \immediate\write18{for \string^\@percentchar i in (#1.exe #1.bat #1.cmd) 49 | do set >\jobname.aex >\jobname.aex} %$ 50 | \newread\@appexistsfile 51 | \immediate\openin\@appexistsfile\jobname.aex 52 | \expandafter\def\expandafter\@tmp@cr\expandafter{\the\endlinechar} 53 | \endlinechar=-1\relax 54 | \readline\@appexistsfile to \@apppathifexists 55 | \endlinechar=\@tmp@cr 56 | \ifthenelse{\equal{\@apppathifexists}{}} 57 | {\AppExistsfalse} 58 | {\AppExiststrue} 59 | \immediate\closein\@appexistsfile 60 | \DeleteFile{\jobname.aex} 61 | \immediate\typeout{file deleted} 62 | \else 63 | \immediate\write18{which #1 && touch \jobname.aex} 64 | \IfFileExists{\jobname.aex} 65 | {\AppExiststrue 66 | \DeleteFile{\jobname.aex}} 67 | {\AppExistsfalse} 68 | \fi} 69 | \newcommand\minted@resetoptions{} 70 | \newcommand\minted@defopt[1]{ 71 | \expandafter\def\expandafter\minted@resetoptions\expandafter{% 72 | \minted@resetoptions 73 | \@namedef{minted@opt@#1}{}}} 74 | \newcommand\minted@opt[1]{ 75 | \expandafter\detokenize% 76 | \expandafter\expandafter\expandafter{\csname minted@opt@#1\endcsname}} 77 | \newcommand\minted@define@opt[3][]{ 78 | \minted@defopt{#2} 79 | \ifthenelse{\equal{#1}{}}{ 80 | \define@key{minted@opt}{#2}{\@namedef{minted@opt@#2}{#3}}} 81 | {\define@key{minted@opt}{#2}[#1]{\@namedef{minted@opt@#2}{#3}}}} 82 | \newcommand\minted@define@switch[3][]{ 83 | \minted@defopt{#2} 84 | \define@booleankey{minted@opt}{#2} 85 | {\@namedef{minted@opt@#2}{#3}} 86 | {\@namedef{minted@opt@#2}{#1}}} 87 | \minted@defopt{extra} 88 | \newcommand\minted@define@extra[1]{ 89 | \define@key{minted@opt}{#1}{ 90 | \expandafter\def\expandafter\minted@opt@extra\expandafter{% 91 | \minted@opt@extra,#1=##1}}} 92 | \newcommand\minted@define@extra@switch[1]{ 93 | \define@booleankey{minted@opt}{#1} 94 | {\expandafter\def\expandafter\minted@opt@extra\expandafter{% 95 | \minted@opt@extra,#1}} 96 | {\expandafter\def\expandafter\minted@opt@extra\expandafter{% 97 | \minted@opt@extra,#1=false}}} 98 | \minted@define@switch{texcl}{-P texcomments} 99 | \minted@define@switch{mathescape}{-P mathescape} 100 | \minted@define@switch{linenos}{-P linenos} 101 | \minted@define@switch{startinline}{-P startinline} 102 | \minted@define@switch[-P funcnamehighlighting=False]% 103 | {funcnamehighlighting}{-P funcnamehighlighting} 104 | \minted@define@opt{gobble}{-F gobble:n=#1} 105 | \minted@define@opt{bgcolor}{#1} 106 | \minted@define@extra{frame} 107 | \minted@define@extra{framesep} 108 | \minted@define@extra{framerule} 109 | \minted@define@extra{rulecolor} 110 | \minted@define@extra{numbersep} 111 | \minted@define@extra{firstnumber} 112 | \minted@define@extra{stepnumber} 113 | \minted@define@extra{firstline} 114 | \minted@define@extra{lastline} 115 | \minted@define@extra{baselinestretch} 116 | \minted@define@extra{xleftmargin} 117 | \minted@define@extra{xrightmargin} 118 | \minted@define@extra{fillcolor} 119 | \minted@define@extra{tabsize} 120 | \minted@define@extra{fontfamily} 121 | \minted@define@extra{fontsize} 122 | \minted@define@extra{fontshape} 123 | \minted@define@extra{fontseries} 124 | \minted@define@extra{formatcom} 125 | \minted@define@extra{label} 126 | \minted@define@extra@switch{numberblanklines} 127 | \minted@define@extra@switch{showspaces} 128 | \minted@define@extra@switch{resetmargins} 129 | \minted@define@extra@switch{samepage} 130 | \minted@define@extra@switch{showtabs} 131 | \minted@define@extra@switch{obeytabs} 132 | \newsavebox{\minted@bgbox} 133 | \newenvironment{minted@colorbg}[1]{ 134 | \def\minted@bgcol{#1} 135 | \noindent 136 | \begin{lrbox}{\minted@bgbox} 137 | \begin{minipage}{\linewidth-2\fboxsep}} 138 | {\end{minipage} 139 | \end{lrbox}% 140 | \colorbox{\minted@bgcol}{\usebox{\minted@bgbox}}} 141 | \newwrite\minted@code 142 | \newcommand\minted@savecode[1]{ 143 | \immediate\openout\minted@code\jobname.pyg 144 | \immediate\write\minted@code{#1} 145 | \immediate\closeout\minted@code} 146 | \newcommand\minted@pygmentize[2][\jobname.pyg]{ 147 | \def\minted@cmd{pygmentize -l #2 -f latex -F tokenmerge 148 | \minted@opt{gobble} \minted@opt{texcl} \minted@opt{mathescape} 149 | \minted@opt{startinline} \minted@opt{funcnamehighlighting} 150 | \minted@opt{linenos} -P "verboptions=\minted@opt{extra}" 151 | -o \jobname.out.pyg #1} 152 | \immediate\write18{\minted@cmd} 153 | % For debugging, uncomment: 154 | %\immediate\typeout{\minted@cmd} 155 | \ifthenelse{\equal{\minted@opt@bgcolor}{}} 156 | {} 157 | {\begin{minted@colorbg}{\minted@opt@bgcolor}} 158 | \input{\jobname.out.pyg} 159 | \ifthenelse{\equal{\minted@opt@bgcolor}{}} 160 | {} 161 | {\end{minted@colorbg}} 162 | \DeleteFile{\jobname.out.pyg}} 163 | \newcommand\minted@usedefaultstyle{\usemintedstyle{default}} 164 | \newcommand\usemintedstyle[1]{ 165 | \renewcommand\minted@usedefaultstyle{} 166 | \immediate\write18{pygmentize -S #1 -f latex > \jobname.pyg} 167 | \input{\jobname.pyg}} 168 | \newcommand\mint[3][]{ 169 | \DefineShortVerb{#3} 170 | \minted@resetoptions 171 | \setkeys{minted@opt}{#1} 172 | \SaveVerb[aftersave={ 173 | \UndefineShortVerb{#3} 174 | \minted@savecode{\FV@SV@minted@verb} 175 | \minted@pygmentize{#2} 176 | \DeleteFile{\jobname.pyg}}]{minted@verb}#3} 177 | \newcommand\minted@proglang[1]{} 178 | \newenvironment{minted}[2][] 179 | {\VerbatimEnvironment 180 | \renewcommand{\minted@proglang}[1]{#2} 181 | \minted@resetoptions 182 | \setkeys{minted@opt}{#1} 183 | \begin{VerbatimOut}[codes={\catcode`\^^I=12}]{\jobname.pyg}}% 184 | {\end{VerbatimOut} 185 | \minted@pygmentize{\minted@proglang{}} 186 | \DeleteFile{\jobname.pyg}} 187 | \newcommand\inputminted[3][]{ 188 | \minted@resetoptions 189 | \setkeys{minted@opt}{#1} 190 | \minted@pygmentize[#3]{#2}} 191 | \newcommand\newminted[3][]{ 192 | \ifthenelse{\equal{#1}{}} 193 | {\def\minted@envname{#2code}} 194 | {\def\minted@envname{#1}} 195 | \newenvironment{\minted@envname} 196 | {\VerbatimEnvironment\begin{minted}[#3]{#2}} 197 | {\end{minted}} 198 | \newenvironment{\minted@envname *}[1] 199 | {\VerbatimEnvironment\begin{minted}[#3,##1]{#2}} 200 | {\end{minted}}} 201 | \newcommand\newmint[3][]{ 202 | \ifthenelse{\equal{#1}{}} 203 | {\def\minted@shortname{#2}} 204 | {\def\minted@shortname{#1}} 205 | \expandafter\newcommand\csname\minted@shortname\endcsname[2][]{ 206 | \mint[#3,##1]{#2}##2}} 207 | \newcommand\newmintedfile[3][]{ 208 | \ifthenelse{\equal{#1}{}} 209 | {\def\minted@shortname{#2file}} 210 | {\def\minted@shortname{#1}} 211 | \expandafter\newcommand\csname\minted@shortname\endcsname[2][]{ 212 | \inputminted[#3,##1]{#2}{##2}}} 213 | \@ifundefined{minted@float@within} 214 | {\newfloat{listing}{h}{lol}} 215 | {\newfloat{listing}{h}{lol}[\minted@float@within]} 216 | \newcommand\listingscaption{Listing} 217 | \floatname{listing}{\listingscaption} 218 | \newcommand\listoflistingscaption{List of listings} 219 | \providecommand\listoflistings{\listof{listing}{\listoflistingscaption}} 220 | \AtBeginDocument{ 221 | \minted@usedefaultstyle} 222 | \AtEndOfPackage{ 223 | \ifnum\pdf@shellescape=1\relax\else 224 | \PackageError{minted} 225 | {You must invoke LaTeX with the 226 | -shell-escape flag} 227 | {Pass the -shell-escape flag to LaTeX. Refer to the minted.sty 228 | documentation for more information.}\fi 229 | \TestAppExists{pygmentize} 230 | \ifAppExists\else 231 | \PackageError{minted} 232 | {You must have `pygmentize' installed 233 | to use this package} 234 | {Refer to the installation instructions in the minted 235 | documentation for more information.} 236 | \fi} 237 | \endinput 238 | %% 239 | %% End of file `minted.sty'. 240 | --------------------------------------------------------------------------------