[git] Start writing cucumber tests.

* First scenario for cherry-pick tests.
* GitCucumberWorld to contain environment variables visible from everywhere.
* Move initialization stuff from GitLightTest to static methods of GitTestInitUtil to reuse in GeneralStepdefs.
* Add cucumber-jvm & cucumber-groovy to git4idea classpath.
This commit is contained in:
Kirill Likhodedov
2013-01-02 17:23:24 +04:00
parent fb3f5870c3
commit 87e2a7e40d
8 changed files with 260 additions and 53 deletions
+4
View File
@@ -8,6 +8,8 @@
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/testFramework" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/test-stepdefs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/test-features" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
@@ -73,6 +75,8 @@
</orderEntry>
<orderEntry type="library" scope="TEST" name="Groovy" level="project" />
<orderEntry type="module" module-name="dvcs" />
<orderEntry type="library" scope="TEST" name="cucumber-jvm" level="project" />
<orderEntry type="library" scope="TEST" name="cucumber-groovy" level="project" />
</component>
</module>
@@ -0,0 +1,88 @@
package git4idea
import com.intellij.dvcs.test.MockVirtualFile
import com.intellij.notification.Notification
import com.intellij.openapi.vcs.FilePathImpl
import com.intellij.openapi.vcs.changes.Change
import com.intellij.openapi.vcs.changes.ChangeListManager
import com.intellij.openapi.vcs.changes.LocalChangeList
import com.intellij.openapi.vcs.history.VcsRevisionNumber
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile
import com.intellij.testFramework.vcs.MockChangeListManager
import com.intellij.testFramework.vcs.MockContentRevision
import git4idea.history.browser.GitCherryPicker
import git4idea.history.browser.GitCommit
import git4idea.history.browser.SHAHash
import git4idea.history.wholeTree.AbstractHash
import git4idea.test.TestNotificator
import static com.intellij.dvcs.test.Executor.echo
import static cucumber.runtime.groovy.EN.*
import static git4idea.GitCucumberWorld.*
import static git4idea.test.GitExecutor.git
import static git4idea.test.GitScenarios.checkout
import static junit.framework.Assert.assertEquals
/**
*
* @author Kirill Likhodedov
*/
String remCommit
Given(~'^(enabled|disabled) auto-commit in the settings$') { String state ->
boolean enabled = state.equals("enabled")
myPlatformFacade.getSettings(myProject).setAutoCommitOnCherryPick(enabled);
}
Given(~'^branch "([^"]*)" with commit "([^"]*)" by "([^"]*)" modifying (.+):$') { String branch, String commitMessage, String author,
String file, String content ->
checkout(myRepository, branch)
echo(file, content)
git("commit -am $commitMessage --author '$author <$author@example.com>'")
checkout(myRepository, "master")
}
When(~'^I cherry-pick the commit "(.+)"$') { String msg ->
String hash = git("log --grep $msg --pretty=%H --all");
remCommit = hash
new GitCherryPicker(myProject, myGit, myPlatformFacade, myPlatformFacade.getSettings(myProject).isAutoCommitOnCherryPick())
.cherryPick(Collections.singletonMap(myRepository, Collections.singletonList(commit(hash, msg))));
}
private GitCommit commit(String hash, String message) {
AbstractHash ahash = AbstractHash.create(hash);
List<Change> changes = new ArrayList<Change>();
changes.add(new Change(null, new MockContentRevision(new FilePathImpl(new MockVirtualFile("name")), VcsRevisionNumber.NULL)));
return new GitCommit(NullVirtualFile.INSTANCE, ahash, SHAHash.emulate(ahash), "John Smith", null, null, message, message,
null, null, null, null, null, null, null, changes, 0);
}
Then(~'^the last commit is$') { String message ->
String actual = git("log -1 --pretty=%B");
message = message.replace("#hash", remCommit)
assertEquals("Commit doesn't match", message, actual);
}
And(~'^notification "([^"]*)" is shown$') { String title ->
assertEquals "Notification title is incorrect", title, lastNotification().title
}
private Notification lastNotification() {
(myPlatformFacade.getNotificator(myProject) as TestNotificator).lastNotification
}
And(~'^no new changelists are created$') {->
assertOnlyDefaultChangelist()
}
void assertOnlyDefaultChangelist() {
String DEFAULT = MockChangeListManager.DEFAULT_CHANGE_LIST_NAME;
assertChangeLists( [DEFAULT], DEFAULT)
}
void assertChangeLists(Collection<String> changeLists, String activeChangelist) {
ChangeListManager changeListManager = myPlatformFacade.getChangeListManager(myProject)
List<LocalChangeList> lists = changeListManager.changeLists
Collection<String> listNames = lists.collect { it.name }
assertEquals "Change lists are different", changeLists.toSet(), listNames.toSet()
assertEquals "Wrong active changelist", activeChangelist, changeListManager.defaultChangeList.name
}
@@ -0,0 +1,47 @@
package git4idea
import com.intellij.dvcs.test.MockProject
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import git4idea.test.GitTestImpl
import git4idea.test.GitTestPlatformFacade
import static com.intellij.dvcs.test.Executor.cd
import static com.intellij.dvcs.test.Executor.mkdir
import static com.intellij.dvcs.test.Executor.touch
import static cucumber.runtime.groovy.EN.Given
import static cucumber.runtime.groovy.Hooks.After
import static cucumber.runtime.groovy.Hooks.Before
import static git4idea.GitCucumberWorld.*
import static git4idea.test.GitExecutor.git
import static git4idea.test.GitScenarios.checkout
import static git4idea.test.GitTestInitUtil.createRepository
/**
* General step definitions and hooks used by all cucumber tests.
*
* @author Kirill Likhodedov
*/
Before() {
myTestRoot = FileUtil.createTempDirectory("", "").getPath()
cd myTestRoot
myProjectRoot = mkdir ("project")
myProject = new MockProject(myProjectRoot)
myPlatformFacade = new GitTestPlatformFacade()
myGit = new GitTestImpl()
cd(myProjectRoot)
myRepository = createRepository(myProjectRoot, myPlatformFacade, myProject)
}
After() {
FileUtil.delete(new File(myTestRoot))
Disposer.dispose(myProject)
}
Given(~'^file (.*) on master:$') { String filename, String content ->
checkout(myRepository, "master")
touch(filename, content)
git("add $filename")
git("commit -m 'adding $filename'")
}
@@ -0,0 +1,28 @@
Feature: Git Cherry-Pick When Auto-Commit is selected
Background:
Given enabled auto-commit in the settings
Given file file.txt on master:
"""
first line
last line (space is to have possibility to avoid conflicts)
"""
Given branch "feature" with commit "fix_1" by "John Bro" modifying file.txt:
"""
first line
last line on branch feature
"""
Scenario: Simple cherry-pick
When I cherry-pick the commit "fix_1"
Then the last commit is
"""
fix_1
(cherry picked from commit #hash)
"""
And notification "Cherry-pick successful" is shown
And no new changelists are created
@@ -0,0 +1,22 @@
package git4idea;
import com.intellij.dvcs.test.MockProject;
import git4idea.commands.Git;
import git4idea.repo.GitRepository;
/**
* <p>The container of test environment variables which should be visible from any step definition script.</p>
* <p>Most of the fields are populated in the Before hook of the {@link GeneralStepdefs}.</p>
*
* @author Kirill Likhodedov
*/
public class GitCucumberWorld {
public static String myTestRoot;
public static String myProjectRoot;
public static MockProject myProject;
public static GitPlatformFacade myPlatformFacade;
public static Git myGit;
public static GitRepository myRepository;
}
@@ -16,13 +16,11 @@
package git4idea.test
import com.intellij.dvcs.test.MockProject
import com.intellij.dvcs.test.MockVirtualFile
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import git4idea.GitPlatformFacade
import git4idea.commands.Git
import git4idea.repo.GitRepository
import git4idea.repo.GitRepositoryImpl
import org.junit.After
import org.junit.Before
/**
@@ -34,30 +32,26 @@ import org.junit.Before
*
* @author Kirill Likhodedov
*/
@Mixin(GitExecutor)
class GitLightTest {
private static final String USER_NAME = "John Doe";
private static final String USER_EMAIL = "John.Doe@example.com";
class GitLightTest extends GitExecutor {
/**
* The file system root of test files.
* Automatically deleted on {@link #tearDown()}.
* Tests should create new files only inside this directory.
*/
protected String myTestRoot
public String myTestRoot
/**
* The file system root of the project. All project should locate inside this directory.
*/
protected String myProjectRoot
public String myProjectRoot
protected MockProject myProject
protected GitPlatformFacade myPlatformFacade
protected Git myGit
public MockProject myProject
public GitPlatformFacade myPlatformFacade
public Git myGit
@Before
protected void setUp() {
public void setUp() {
myTestRoot = FileUtil.createTempDirectory("", "").getPath()
cd myTestRoot
myProjectRoot = mkdir ("project")
@@ -72,26 +66,8 @@ class GitLightTest {
Disposer.dispose(myProject)
}
protected GitRepository createRepository(String rootDir) {
initRepo(rootDir)
// TODO this smells hacky
// the constructor and notifyListeners() should probably be private
// getPresentableUrl should probably be final, and we should have a better VirtualFile implementation for tests.
GitRepository repository = new GitRepositoryImpl(new MockVirtualFile(rootDir), myPlatformFacade, myProject, myProject, true) {
@Override
protected void notifyListeners() {
}
@Override
String getPresentableUrl() {
return rootDir;
}
}
registerRepository(repository)
return repository
public GitRepository createRepository(String rootDir) {
return GitTestInitUtil.createRepository(rootDir, myPlatformFacade, myProject)
}
/**
@@ -103,23 +79,4 @@ class GitLightTest {
cd source
git("remote add $targetName $myTestRoot/$target");
}
private void registerRepository(GitRepositoryImpl repository) {
((GitTestRepositoryManager)myPlatformFacade.getRepositoryManager(myProject)).add(repository)
}
private void initRepo(String repoRoot) {
cd repoRoot
git("init")
setupUsername();
touch("file.txt")
git("add file.txt")
git("commit -m initial")
}
private void setupUsername() {
git("config user.name $USER_NAME")
git("config user.email $USER_EMAIL")
}
}
@@ -197,7 +197,7 @@ public class GitTestImpl implements Git {
@NotNull String hash,
boolean autoCommit,
@NotNull GitLineHandlerListener... listeners) {
throw new UnsupportedOperationException();
execute(repository, "cherry-pick -x ${autoCommit ? "" : "-n"} $hash")
}
@NotNull
@@ -0,0 +1,61 @@
package git4idea.test
import com.intellij.dvcs.test.MockVirtualFile
import com.intellij.openapi.project.Project
import git4idea.GitPlatformFacade
import git4idea.repo.GitRepository
import git4idea.repo.GitRepositoryImpl
/**
*
* @author Kirill Likhodedov
*/
class GitTestInitUtil {
private static final String USER_NAME = "John Doe";
private static final String USER_EMAIL = "John.Doe@example.com";
/**
* Init, set up username and make initial commit.
* @param repoRoot
*/
public static void initRepo(String repoRoot) {
com.intellij.dvcs.test.Executor.cd repoRoot
git4idea.test.GitExecutor.git("init")
setupUsername();
com.intellij.dvcs.test.Executor.touch("initial.txt")
git4idea.test.GitExecutor.git("add initial.txt")
git4idea.test.GitExecutor.git("commit -m initial")
}
public static void setupUsername() {
git4idea.test.GitExecutor.git("config user.name $USER_NAME")
git4idea.test.GitExecutor.git("config user.email $USER_EMAIL")
}
public static GitRepository createRepository(String rootDir, GitPlatformFacade platformFacade, Project project) {
GitTestInitUtil.initRepo(rootDir)
// TODO this smells hacky
// the constructor and notifyListeners() should probably be private
// getPresentableUrl should probably be final, and we should have a better VirtualFile implementation for tests.
GitRepository repository = new GitRepositoryImpl(new MockVirtualFile(rootDir), platformFacade, project, project, true) {
@Override
protected void notifyListeners() {
}
@Override
String getPresentableUrl() {
return rootDir;
}
}
registerRepository(repository, platformFacade, project)
return repository
}
private static void registerRepository(GitRepository repository, GitPlatformFacade platformFacade, Project project) {
((GitTestRepositoryManager)platformFacade.getRepositoryManager(project)).add(repository)
}
}