Vim - previmでmermaidに対応しました
Shibaで図を書いてTracで共有するを見てmermaidを知りました。
参考: mermaid.jsが素晴らしいけどなかなか使ってる人見かけないので実例晒す(追記あり)
面白そうだし、上記の公式サイトにmarked対応のサンプルもあったのでprevimでも対応しました。
下記のようにコードブロックのタイプをmermaid
としてもらえればOKです。
mermaid自体の具体的な書き方は公式サイトを参考にしてください。
(私も全然分かっていません)
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->E;
```
あとは普通のmarkdownと同様にプレビューされます。
Vim - 文字列連結で再代入する場合はjoinを使う方が早そう
概要
自作プラグインのコードに以下のようなTODOが残っていました。
" TODO リストじゃなくて普通に文字列連結にする(テスト書く) for line in s:do_external_parse(a:lines) let escaped = 適当な処理 call add(converted_lines, escaped) endfor return join(converted_lines, "\\n")
ここでは文字列の配列をぐるぐる回して処理を行い、最終的に改行区切りの文字列としています。
join
で書いたものの文字列連結の方が早いのではと思って上記のようなTODOコメントを残していました。
今日このTODOを消化しようと思い、本当に文字列連結の方が早いのか計測しました。
先に結論
- 10回程度の連結なら大差ない
- 3000回ともなると圧倒的にjoinが早い
- joinの方が実装もシンプル
環境
- Mac OS X 10.9.5
- MacVim Custom Version 7.4 (KaoriYa 20150707)
ベンチマーク
h1mesuke/vim-benchmarkを使用します。
テストデータは1行85文字が3000行です。(3000回連結される)
let s:lines = [] for s:n in range(3000) call add(s:lines, " * 注意:拡張子が`.md`の場合は`markdown`ではなく`modula2`として認識されてしまいます。その場合は以下の設定を.vimrcに記述してください") endfor let s:bm = benchmark#new("concat string") function! s:bm.operator_for() let result = "" let delim = "" for line in s:lines let result = result . delim . line let delim = "\\n" endfor endfunction function! s:bm.operator_while() let result = "" let delim = "" let n = 0 let length = len(s:lines) while n < length let result = result . delim . s:lines[n] let delim = "\\n" let n += 1 endwhile endfunction function! s:bm.join() let tmp = [] for line in s:lines call add(tmp, line) endfor let result = join(tmp, "\\n") endfunction call s:bm.run(3)
結果は以下の通り。
Benchmark: concat string Trial #1 join : 0.008425 operator_for : 0.348224 operator_while : 0.356583 Trial #2 join : 0.010402 operator_for : 0.353079 operator_while : 0.359111 Trial #3 join : 0.008463 operator_while : 0.347276 operator_for : 0.359592
joinが圧倒的に早かった。
Javaで+
連結すると遅いように、Vim Scriptでも気をつけた方がいいのかな。
ちなみに10回程度の連結なら大差ない。
Benchmark: concat string Trial #1 join : 0.000046 operator_for : 0.000063 operator_while : 0.000076 Trial #2 join : 0.000051 operator_for : 0.000080 operator_while : 0.000083 Trial #3 join : 0.000048 operator_for : 0.000066 operator_while : 0.000082
おわりに
「推測するな、計測せよ」の大事さ。
capistrano3のコードを読んで仕組みを理解する
メモです。
はじめに
capistrano3の概要を知るには以下の記事がとても参考になる。
業務での使用も経て何となく分かったつもりだったが、デフォルトで色々やってくれるのが逆に少し気持ち悪かった。
内部を理解しないことには気持ち悪さは解消されそうにないのでコードを読んだ。
だいぶ理解したものの、すぐに忘れそうなのでメモしておく。
対象
- capistrano3について何となく知っている。使ったことがある
- capistranoの内部でどういう風に処理が走っているかは知らない
- capistranoのバージョンは3.4.0
長くなったので、各項目のまとめだけ読むと手っ取り早いと思う。
1. cap install
入り口としてcap install
が何故実行出来るのか、から。
bin/cap
の中を覗く。
require 'capistrano/all' Capistrano::Application.new.run
capistrano/all
を読み込みCapistrano::Application
を実行しているのみ。
1.1. capistrano/all
require 'capistrano/version' require 'capistrano/version_validator' require 'capistrano/i18n' require 'capistrano/dsl' require 'capistrano/application' require 'capistrano/configuration'
ここは特筆することなさそう。
1.2. capistrano/application
Rake::Application
を継承。bin/cap
にあったCapistrano::Application.new.run
のクラス。
クラスがインスタンス化されるときの処理(initialize)が以下のようになっている。
自前のCapfile
に加えて、lib/Capfile
がRakefileとして読み込まれる。
def initialize super @rakefiles = %w{capfile Capfile capfile.rb Capfile.rb} << capfile end # allows the `cap install` task to load without a capfile def capfile File.expand_path(File.join(File.dirname(__FILE__),'..','Capfile')) end
なおrun
はRakeに処理を委譲しているだけ。
def run Rake.application = self super end
1.3. lib/Capfile
cap install
した時に作られるCapfile
ではなくライブラリ側のCapfile
。
include Capistrano::DSL require 'capistrano/install'
lib/capistrano/install.rb
の定義は1行だけ。
load File.expand_path(File.join(File.dirname(__FILE__),'tasks/install.rake'))
このあと見て行くsetup
やdeploy
でもほとんど同じで、最終的に.rake
ファイルを読み込むようになっている。
`lib/capistrano/tasks/install.rake` desc 'Install Capistrano, cap install STAGES=staging,production' task :install do # ... end
:install
にcap install
時の処理が書かれている。
つまり色々とファイルを自動生成してくれる。
1.4. cap installのまとめ
bin/cap
がcapistrano/all
を読み込み、Cap用のRakeを実行するcapistrano/all
により基本的なDSLが定義される- 中で読まれる
capistrano/application
によりライブラリ側のCapfile
が読まれる - ライブラリの
Capfile
にはinstall
だけが定義されている- なので
cap install
が実行出来る
- なので
- 中で読まれる
cap install
すると生成されるCapfile
は不要なコメントアウト行を除くと以下の通り。
# Load DSL and set up stages require 'capistrano/setup' # Include default deployment tasks require 'capistrano/deploy' # Load custom tasks from `lib/capistrano/tasks` if you have any defined Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
setup
とdeploy
について読み進めていく。
(lib/capistrano/tasks/*.rake
についてはコメントの通りカスタム定義なので読むところはなし)
2. capistrano/setup
include Capistrano::DSL namespace :load do task :defaults do load 'capistrano/defaults.rb' end end stages.each do |stage| Rake::Task.define_task(stage) do set(:stage, stage.to_sym) invoke 'load:defaults' load deploy_config_path load stage_config_path.join("#{stage}.rb") load "capistrano/#{fetch(:scm)}.rb" I18n.locale = fetch(:locale, :en) configure_backend end end require 'capistrano/dotfile'
処理の流れは何となく読み取れる。
- stage(たぶんproductionとかstagingとか)ごとの設定を読み込んでいる
- defaultsっていうのを読み込んでいる。きっとデフォルト設定だろう
- scmの定義を読み込んでいる
- その他なんか設定している
もう少しコードを読んでみる。
2.1. stage(たぶんproductionとかstagingとか)ごとの設定を読み込んでいる
いくつかプロパティが出てくるが、これらはどこで定義されているか。
stages
前述のcapistrano/dsl
にて読み込まれるlib/capistrano/dsl/stages.rb
に定義されている。
def stages Dir[stage_definitions].map { |f| File.basename(f, '.rb') } end def stage_definitions stage_config_path.join('*.rb') end
stage_config_path
はlib/capistrano/dsl/paths.rb
に定義されている。
def stage_config_path Pathname.new fetch(:stage_config_path, 'config/deploy') end
:stage_config_path
が設定されていればそのパス、設定されていなければconfig/deploy
のパスを取得している。
cap install
するとconfig/deploy/{production,staging}.rb
を作成してくれるので、デフォルトではこれらが取得される。
File.basename
なので結果としては['production', 'staging']
という値がstages
の戻り値になっているはず。
deploy_config_path
上記のstage_config_path
と同じくlib/capistrano/dsl/paths.rb
に定義されている。
def deploy_config_path Pathname.new fetch(:deploy_config_path, 'config/deploy.rb') end
こちらもcap install
で作られるconfig/deploy.rb
がデフォルトである。
なおsetup
のコードを再び見ると、loadの順番は次のようになっている。
load deploy_config_path load stage_config_path.join("#{stage}.rb")
config/deploy.rb
を読み込んでからconfig/deploy/*.rb
を読み込む。
なので両者で同じ定義をしているとconfig/deploy/*.rb
が勝ちそうな気がする。試していない。
2.2. defaultsっていうのを読み込んでいる
その名の通り変数のデフォルト値を定義している。
set_if_empty :scm, :git set_if_empty :branch, :master set_if_empty :deploy_to, -> { "/var/www/#{fetch(:application)}" } set_if_empty :tmp_dir, "/tmp" set_if_empty :default_env, {} set_if_empty :keep_releases, 5 set_if_empty :format, :pretty set_if_empty :log_level, :debug set_if_empty :pty, false set_if_empty :local_user, -> { Etc.getlogin }
多くの変数については、自動生成されるdeploy.rb
にコメントアウトされた内容として書かれている。
# Default value for :scm is :git # set :scm, :git ...
2.3. scmの定義を読み込んでいる
前述の通り:scm
はdeploy.rb
などで定義するがデフォルトはgitである。
lib/capistrano/git.rb
が読み込まれ、このあとのdeploy
で必要なコマンドが定義される。
あとでまた詳しく見るとする。
2.4. その他なんか設定している
configure_backendについて。
def configure_backend backend.configure do |sshkit| sshkit.format = fetch(:format) sshkit.output_verbosity = fetch(:log_level) sshkit.default_env = fetch(:default_env) sshkit.backend = fetch(:sshkit_backend, SSHKit::Backend::Netssh) sshkit.backend.configure do |backend| backend.pty = fetch(:pty) backend.connection_timeout = fetch(:connection_timeout) backend.ssh_options = (backend.ssh_options || {}).merge(fetch(:ssh_options,{})) end end end
sshkitの設定ぽい。処理の全体像とは関係が低そうなのでこれ以上は追わない。
2.5. capistrano/setupのまとめ
- SCMやデプロイ先などアプリケーション固有の変数を初期化
config/deploy.rb
の読み込みconfig/deploy/*.rb
の読み込み- SCM固有のコマンド定義を読み込み
- SSH設定を読み込み
3. capistrano/deploy
require 'capistrano/framework' load File.expand_path("../tasks/deploy.rake", __FILE__)
capistrano/framework
については以下のようになっている。
load File.expand_path("../tasks/framework.rake", __FILE__) require 'capistrano/install'
ということで、framework.rake
とdeploy.rake
を読み進める必要がある。
3.1. framework.rake
冒頭の参考記事(2つ目)にもある通り、このファイルはデプロイフローの雛形を定義している。
namespace :deploy do desc 'Start a deployment, make sure server(s) ready.' task :starting do end # ... desc 'Rollback to previous release.' task :rollback do %w{ starting started reverting reverted publishing published finishing_rollback finished }.each do |task| invoke "deploy:#{task}" end end end desc 'Deploy a new release.' task :deploy do set(:deploying, true) %w{ starting started updating updated publishing published finishing finished }.each do |task| invoke "deploy:#{task}" end end task default: :deploy
deploy
/rollback
は共に必要なコマンドを実行するだけ- このあとで詳しく見る
deploy
/rollback
以外のコマンドはデフォルトでは何もしない- 具体的な処理は
deploy.rake
で定義される
- 具体的な処理は
namespace :deploy
のデフォルトは:deploy
- なので
cap deploy
はdeploy
が呼ばれる
- なので
テンプレートメソッドっぽい。
3.2. deploy.rake
:starting
とか:updating
とか、framework.rake
のいくつかのコマンドが再定義されている。
3.2.1. deploy.rake -- deploy
フェーズ毎に簡単に処理を見てみる。
deploy:starting
該当部分だけ抜き出す。
task :starting do invoke 'deploy:check' invoke 'deploy:set_previous_revision' end desc 'Check required files and directories exist' task :check do invoke "#{scm}:check" invoke 'deploy:check:directories' invoke 'deploy:check:linked_dirs' invoke 'deploy:check:make_linked_dirs' invoke 'deploy:check:linked_files' end task :set_previous_revision do on release_roles(:all) do target = release_path.join('REVISION') if test "[ -f #{target} ]" set(:previous_revision, capture(:cat, target, '2>/dev/null')) end end end
- check系のタスクではファイルやディレクトリのチェックや準備を行う
deploy:check:directories
などのタスクは同一ファイルに定義されているexecute :mkdir, '-p', shared_path, releases_path
などをしている
:set_previous_revision
ではリリース前の最新リビジョンを変数に保存しておく- capを使ってデプロイするとデプロイ先にリビジョンが書かれた
REVISION
というファイルが作られる - バージョンによってはないらしい。参考: デプロイしたリビジョンをファイルに書き出す
- capを使ってデプロイするとデプロイ先にリビジョンが書かれた
deploy:started
デフォルトのまま。何もしない。
deploy:updating
:updating
には依存があり、先に:new_release_path
が行われる。
まずは:new_release_path
から読む。
task :new_release_path do set_release_path end
set_release_path
はlib/capistrano/dsl/paths.rb
に定義されている。
def releases_path deploy_path.join('releases') end def set_release_path(timestamp=now) set(:release_timestamp, timestamp) set(:release_path, releases_path.join(timestamp)) end
- リリース先のパスを変数に設定している
releases/20150080072500
みたいなパス- デプロイの構造は公式のStructureを参照
次にupdating
の処理の中身を読む。
task :updating => :new_release_path do invoke "#{scm}:create_release" invoke "deploy:set_current_revision" invoke 'deploy:symlink:shared' end namespace :symlink do # ... desc 'Symlink files and directories from shared to release' task :shared do invoke 'deploy:symlink:linked_files' invoke 'deploy:symlink:linked_dirs' end # ... end desc "Place a REVISION file with the current revision SHA in the current release path" task :set_current_revision do invoke "#{scm}:set_current_revision" on release_roles(:all) do within release_path do execute :echo, "\"#{fetch(:current_revision)}\" >> REVISION" end end end
:set_current_revision
は前述のREVISION
にリビジョンを書き込んでいるだけ:symlink:shared
はsymlinkの必要があるディレクトリやファイルがあれば作っている- 上記のリンク(Structure)の
shared
を参照
- 上記のリンク(Structure)の
:create_release
については少し詳しく読む。
コードを全部載せると長いので概要だけ。
# lib/capistrano/tasks/git.rake desc 'Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt' task :wrapper do # ... end desc 'Clone the repo to the cache' task clone: :'git:wrapper' do # ... end desc 'Update the repo mirror to reflect the origin state' task update: :'git:clone' do # ... end desc 'Copy repo to releases' task create_release: :'git:update' do # ... end
- 依存関係を考慮した実行順は wrapper -> clone -> update -> create_release
- wrapper
- 専用のgit-ssh.shを配置する
- clone
- cloneされていなければcloneする
git :clone, '--mirror', repo_url, repo_path
- clone済みなら何もしない
- デプロイ先にrepo/HEADがあるかどうか
- 上記のリンク(Structure)の
repo
を参照
- 上記のリンク(Structure)の
- デプロイ先にrepo/HEADがあるかどうか
- cloneされていなければcloneする
- update
- repoの中で実行される
git :remote, :update
- create_release
- repoの中で実行される
- :repo_tree がある場合
git :archive, fetch(:branch), tree, "| tar -x --strip-components #{components} -f - -C", release_path
- ない場合
git :archive, fetch(:branch), '| tar -x -f - -C', release_path
deploy:updated
デフォルトのまま。何もしない。
deploy:publishing
task :publishing do invoke 'deploy:symlink:release' end namespace :symlink do desc 'Symlink release to current' task :release do on release_roles :all do tmp_current_path = release_path.parent.join(current_path.basename) execute :ln, '-s', release_path, tmp_current_path execute :mv, tmp_current_path, current_path.parent end end end
current -> /var/www/my_app_name/releases/20150120114500/
みたいなsymlinkを作っているだけ。
デプロイ先の構造については上記のリンク(Structure)を参照。
deploy:published
デフォルトのまま。何もしない。
deploy:finishing
task :finishing do invoke 'deploy:cleanup' end desc 'Clean up old releases' task :cleanup do on release_roles :all do |host| releases = capture(:ls, '-xtr', releases_path).split if releases.count >= fetch(:keep_releases) info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count) directories = (releases - releases.last(fetch(:keep_releases))) if directories.any? directories_str = directories.map do |release| releases_path.join(release) end.join(" ") execute :rm, '-rf', directories_str else info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases)) end end end end
descの通り:keep_releases
を超えた古いリリースファイルを消す作業。
capture(:ls, '-xtr', releases_path).split
は、こんなやり方があるのかとちょっと驚いた。
ls -xtr <pat>
とすることで「水平(x)」に「日付(t)」の「降順(r)」で出力させて、splitすることでそのまま配列として扱っている。
あとt(:keeping_releases ...)
のt
って何だと思ったが、i18nのようだった。
# lib/capistrano/dsl.rb def t(key, options={}) I18n.t(key, options.merge(scope: :capistrano)) end
deploy:finished
task :finished do invoke 'deploy:log_revision' end desc 'Log details of the deploy' task :log_revision do on release_roles(:all) do within releases_path do execute %{echo "#{revision_log_message}" >> #{revision_log}} end end end
リリース先のrevisions.log
にメッセージを書き込む。
revisions.log
についても上記のリンク(Structure)を参照。
3.2.2. deploy.rake -- rollback
deploy:starting
deploy:started
deployと同じ。
deploy:reverting
task :reverting do invoke 'deploy:revert_release' end desc 'Revert to previous release timestamp' task :revert_release => :rollback_release_path do on release_roles(:all) do set(:revision_log_message, rollback_log_message) end end task :rollback_release_path do on release_roles(:all) do releases = capture(:ls, '-xt', releases_path).split if releases.count < 2 error t(:cannot_rollback) exit 1 end last_release = releases[1] set_release_path(last_release) set(:rollback_timestamp, last_release) end end
- リリースが1つしかないならロールバック不可
- 一つ前のリリースを
:release_path
に設定
deploy:reverted
デフォルトのまま。何もしない。
deploy:publishing
処理的にはdeployと同じ。
ただし前述の通り:release_path
が直前のリリースパスになっているので、current
がそれにsymlinkされる。
deploy:published
deployと同じ。(何もしない)
deploy:finishing_rollback
task :finishing_rollback do invoke 'deploy:cleanup_rollback' end desc 'Remove and archive rolled-back release.' task :cleanup_rollback do on release_roles(:all) do last_release = capture(:ls, '-xt', releases_path).split.first last_release_path = releases_path.join(last_release) if test "[ `readlink #{current_path}` != #{last_release_path} ]" execute :tar, '-czf', deploy_path.join("rolled-back-release-#{last_release}.tar.gz"), last_release_path execute :rm, '-rf', last_release_path else debug 'Last release is the current release, skip cleanup_rollback.' end end end
- ロールバックしたリリースはいらないよね、っていう作業
rolled-back-release-#{last_release}.tar.gz
という感じのファイル名でアーカイブ- デプロイ先(currentとかと同じ階層)に置かれる
releases
にあるリリースを消す
deploy:finished
deployと同じ。
3.3. capistrano/deploy のまとめ
capistrano/framework
はフローの雛形を提供している- deploy
- デプロイ先のディレクトリなどを準備する
- 初回のみ
git clone
する - 毎回
git remote update
が行われる git archive <branch>
したものがreleases/<timestamp>
の中に置かれる- 上記リリース物と
current
をsymlinkでくっつける releases
が:keep_releases
を超えないように調整する
- rollback
- 直前のリリース物を
current
にする - 直前のリリース物をアーカイブする
- 直前のリリース物を
releases
から削除する
- 直前のリリース物を
framework
とdeploy
のおかげで利用者としては基本的にはフックを定義するだけで良い。ということをちゃんと理解出来た。
基本処理は分かったとして、一応before
/after
のフックについても仕組みを見ておきたい。
4. before/after
capistrano/dsl.rb
で読み込まれるlib/capistrano/dsl/task_enhancements.rb
にて定義されている。
def before(task, prerequisite, *args, &block) prerequisite = Rake::Task.define_task(prerequisite, *args, &block) if block_given? Rake::Task[task].enhance [prerequisite] end def after(task, post_task, *args, &block) Rake::Task.define_task(post_task, *args, &block) if block_given? post_task = Rake::Task[post_task] Rake::Task[task].enhance do post_task.invoke end end
capistranoというよりはRakeの構文の模様。
Rake で任意のタスクの前後に別のタスクを実行する
4.1. before/after のまとめ
- Rakeに委譲しているだけ
おわりに
整理と備忘のために書いたけど、忘れてもまたドキュメントとコードを読んだ方が分かりやすいような気がしてきた。
「第二回 システムテスト自動化 標準ガイド 読書会」に参加してきた
前回に引き続き参加してきました。
第二回 システムテスト自動化 標準ガイド 読書会
今回は3、4章がテーマ。
3章
http://www.slideshare.net/dnoguchi/3-20150523-48477354
保守性の高いテストスクリプトを書くために、というお話。
- テストスクリプトとプログラミングは似ている
- 良いスクリプトと悪いスクリプト
- スクリプトにはきちんとしたドキュメントを残そうという話
- バージョン管理(Git)やWebDriver/Gebを使えば基本いらないように感じた
- スクリプトの種類(上から下に向かうにつれて、よりよいスクリプト)
- スクリプト前処理
- メンテしやすいようにフォーマットとか定数とか気をつけましょうという話
- 発表者の方も仰っていたけど当然だよねという話
- 3章全体がそんな感じではある
- この本は「基本を書いている」らしいので、そういうレベルのこともあるのかな
- もしくは当時はこれが当然と思われてはいなかったのか
- 会場でのディスカッションにて
4章
実行結果と期待値の比較について。
- 「何を」「どのくらいの粒度で」比較するかを検討するのが大事
- 強く同感
- 比較の種類
- 動的比較、実行後比較(静的比較?)
- 定義及び何のために分けているのかイマイチ不明
- 質問を投げてみたが、みなさんも定義がもやっとしている様子
- 実行後比較については刊行当時のツールの制約があるのかもしれないとのこと
- 単純な比較と複雑な比較
- 単純な比較: 素直に比較を取る
- 複雑な比較: 条件付きで比較を取る
- 例: IDはアカウントによって異なるので差分に含めない
- テストツールとテストハーネスの関係についての図(P142)
- 1つの欠陥につき1つのテストケースが失敗するのが理想
- センシティブかロバストか
- 基本的なところはセンシティブ、詳細なところはロバストがおすすめ戦略
- 実行結果と期待値を等価的に扱うためにフィルタを用いる
- 日付はハイフンに統一するとか
- 例:HTML全部を比較するようなセンシティブなテストで、IDとか日付とかを固定文字列に置換する
- 例:画面のエラーメッセージの順番が定まっていないときにsortする
- 現場の状況(プロジェクトや製品の性質、メンバースキルなど)を理解して方法を選択する
- これは比較に限らずって感じ
感想
前回に引き続き有意義でした。
今回は懇親会にも参加し、色々とお話が聞けたのも良かったです。
- 動的比較と実行後比較はやっぱり分かり辛いよね
- (本編でも議論されていましたが)テスト実行後に出来たファイルを目視確認するとかが実行後比較? -> いやそれは動的じゃない?とか
- データ駆動とキーワード駆動について
- 画面テストではやはりIEは対象外にするのが平和である
- テスト以外の話題も(むしろそっちの方が多かったかも)
- 採用について
- マネジメントについて
- モチベーションについて
参加された方々のポジションも様々で、品質/プロダクティビティエンジニア/人事などなど。
プロダクティビティエンジニアという呼び方は知りませんでした。
分野的にはエンジニアリングプロダクティビティと呼ぶのだとか。噛みそう。
あとお店の食べ物が美味しかった。
私はこの日体調が悪く、前半は普通に喋れていたのですが後半は体調が悪化して口数が減ってしまいました。
前述した「ドキュメントはどの粒度で書くべきか」という話もしたかったのですが体力尽きていた。次回は体調を万全にしておきたい。
直近でのテスト関係のイベントをいくつか教えて頂きました。
- 5/25 Testing Casual Talks #2
- 申し込みdone
- 5/26 【無料開催】ヒンシツ大学ET#07 『ゴール指向の測定と品質保証活動』
- 業務的に行けるか微妙なので迷い中
- 6/20,21 WACATE2015 夏 ~ワタシハソフトウェアテストチョットデキル~ 開催概要
- 迷い中
「第一回 システムテスト自動化 標準ガイド 読書会」に参加してきた
第一回 システムテスト自動化 標準ガイド 読書会に参加してきました。
今回は1、2章がテーマ。
1章
http://www.slideshare.net/fujisawa_y/20150418-46648838
- テスト管理
- TestLinkとか
- テスト設計
- モデルベースドテスト
- 開発に使ったモデルからテストを作るのでなく、テストのためのモデルを再設計する?
- まだリンク先の資料を読んでいない
- PictMasterやCEGTestなどのツールがある
- モデルベースドテスト
- ブラウザテスト
- 負荷テストはJMeterよりGatlingが良いらしい
- 要件や設計のテストって、レビューとは違う?
- シーケンス図や業務フロー図を書いてみることがテストの一つに該当する
- CEGTest使うと漏れが見える
- ただ手法が難しいらしい
2章
スライドはどこかに上がっているのでしょうか?
- ソフトウェア設計自体が、テスティングの自動化自体の成功を左右する
- 最初からテストを意識して設計すると良いよね
- 前述のブラウザテストで例えると、idやclassを最初から振っておくとか
- 最初からテストを意識して設計すると良いよね
- テスターとテストオートメーターが分かれている経験ある人?
- テスターは派遣とか外注、オートメーターは自社というパターンがあるみたい
- テスターとテストオートメーターの分業について
- 賛成/反対に分かれて参加者で意見出し
- 2章の話は原著当時の背景が強く影響している?
- MSのWindowsテスト?(うろ覚え)
- テストスクリプトが複雑になる = メンテコストが高くなる
- あるある
- アドホックテストの自動化は無意味。自動化の前にテスト手法/設計を見直すべき
- 詳細なテストスクリプトから自動化する
- テスト自動化をプロジェクトで導入するには
- 実際に見せる。画面テストを100ケースとか
- QAの世界では4つのコスト(予防、評価、外部失敗、内部失敗)という考えがある
- 気合い