猫でも分かるgit rebaseの使い方

どうも、せっきーです。

gitを使い始めてからはや4年。
よく使われる一通りのgitコマンドは使いこなせる様になったかと思いきや、git rebaseはずっと苦手で、ずっとなあなあにして来ました。




git rebaseは言ってしまえばgitのコミットログをキレイにする為のコマンドなのですが、イマイチその有用性を実感できず、最近までひとつのプルリクにいくつもログが残ったままpushしておりました。

しかしこのままではいかんと思い、このたびgit rebaseをマスターすべく勉強してみました。




git rebaseを理解しようとして挫折する人の一番の壁は、コンフリクトした際に「no branch」に飛ばされてしまう現象じゃないかと個人的には思います。


実際にターミナルの画面を見ながら解説します。
まずは普通の成功例。

こんなログのブランチがあったとします。






例えば修正Bと修正Cのログをひとつにまとめたいと思った場合のコマンドは、

1
git rebase -i HEAD~2

になります。
実際に打ってみます。

するとこんな画面になりますので、
ベースとなるコミットにpick、他とまとめたいコミットにsquashを入力し、

:wqで保存します。すると、

コミットメッセージ編集画面になりますので、1行にまとめて、

同様に:wqで保存します。
すると、

こんな感じでひとつのコミットにまとめられました。

しかしたまにこんな感じのエラーが出て…

この様に(no branch)と言う謎のブランチに飛ばされる事があります。

これはrebaseする事によりコンフリクトが起こる為、自動的にマージ出来ない場合に起きます。

そうなった場合は冷静にコンフリクトしているファイルを確認してそのファイルのコンフリクトを解消して、

1
git add

そして通常ならこのままgit commitしたくなりますが、そうではなく、

1
git rebase --continue

と打ちます。
こうする事でコンフリクトを解消した上で、rebaseできます。

そしてブランチの位置もno branchではなく、元いたブランチに戻って来てます。

さて、ここまででコミットログをキレイに出来たのですが、いよいよコミット結果をリモートブランチにpushしたいのですが、普通に

1
git push origin (hoge)

と打っても以下の様なエラーになります。

なのでここでは-fコマンドを使いましょう。

このオプションは上記エラーがあっても強制的にpushするコマンドなので、自分以外が触っている可能性があるブランチでは使わない様に。

以上、git rebaseのやり方とつまづきドコロでした。

Seleniumのテストを書いてる時にThread.sleepを使わずにwait処理を実装する方法

どうも、せっきーです。
いま業務でseleniumを使ったUI自動テストの実装を進めています。

seleniumは色んな言語で記述できるし、何ならユーザーの動作を記録して自動でテストケースを生成したり、色々できるんですが、その辺の説明は他のブログにお任せします。

今回やりたい事は、タイトルの通りですが、Thread.sleepを使わずに一定時間waitする処理を自前で作る方法についてです。
また、テストケースを記述する言語はJAVAになります。

seleniumでは、何らかのアクション(ボタンのクリックなど)でDOMが変化し、そのDOMの変化を待ってからその値を検証する様なテストケースの場合、その「◯◯が終わるまで待機」と言う処理を実装する方法はいくつかあるのですが、一般的に多く使われるのは、ExpectedConditionsを使ったwait処理ではないかと思います。

ここでは詳しくは説明しませんが、例えば

1
wait.until(ExpectedConditions.titleIs("ページタイトル"));

の様に記述することで、ページタイトルが指定の文字列になるのを待ったり出来ます。

ExpectedConditionsのメソッドは結構色んな種類があるので、大抵の待機条件は作れます。

でも、今回どうしてもオリジナルの待機条件を作る必要があったので、ExpectedConditionsクラスを拡張して、「◯◯秒経ったら次の処理を開始する」為のクラスを作成しました。

Thread.sleepを使えば同様の処理は行えるのですが、どうもThread.sleepはスレッドを停止させる事でバグの原因になる事があるらしいのと、あとコードチェックに使っているSonarQubeでバグとして警告されてしまうので、使えなかったのです。

で、具体的な記述方法ですが、

WaitTimerAttributeCondition.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import java.util.Timer;
import java.util.TimerTask;
public class WaitTimerAttributeCondition implements ExpectedCondition<Boolean> {
private Boolean flag = false;
protected WaitTimerAttributeCondition(Long milisec) {
TimerTask task = new TimerTask() {
public void run() {
flag = true;
}
};
Timer timer = new Timer();
timer.schedule(task, milisec);
}
public Boolean apply(WebDriver wd) {
return flag;
}
}

そして、呼び出し側では、

1
wait.until(new WaitTimerAttributeCondition(5000L));

この様に使います。
上記の例だと、5000ミリ秒、すなわち5秒間処理を待機した後、次の処理を開始します。

ただこの様に、固定の秒数待機して次の処理を行う方法は、ネットワーク速度やマシンスペックなど環境が異なると、場合によっては上手く動作しない可能性もあります。

ただ、今回seleniumでの自動テスト対象になったサイトが、bootstrapを使っており、何らかのアクションにいちいちアニメーションが入って来て、そのアニメーションの終了を検知する必要がどうしてもあったので、実装してみました。

ぜひ参考にして下さい。

初投稿

今日からブログ再開します。
日々のアウトプットがインプットのモチベーションになると言う話は良く聞くので、エンジニアとして日々学んだ事をつらつらとアウトプットしていく予定です。

当方のエンジニアとしての経歴はフロントエンドエンジニア5年、Android、iOSエンジニア半年(2017年2月現在)です。

エンジニアとしての職歴はほとんどがフロントエンドでした。
しかしこれからはスマートフォンのネイティブコードもバリバリ書けるエンジニアを目指しているので、日々邁進していきます。

とりあえず生暖かい目で見守って頂ければ幸いです。