Tuesday, December 20, 2011

IntelliJ IDEA 11

The new version of IntelliJ IDEA is out, and I'm liking it.

Gradle integration: creating a new project from a build.gradle was smooth and easy. Then when dependencies were added to the gradle file, the gradle plugin came in handy. One line added to build.gradle
apply plugin: 'idea'
and then one execution of
gradle idea
updated the dependencies without losing my other settings.

Git integration: it's built-in, but I haven't tried it yet. I'm still making friends with git at the command line. in the meantime, I added .idea, *.ipr and *.iws to the .gitignore list.

Android integration: this is smooth. It was a little rough in the last version. In 11, it's slick so far. Clicking on an R.id.viewName takes me directly to the definition of that layout element in the XML. The IDE also has a GUI editor for creating layouts -- priceless. (I do have an issue with the resources not being regenerated and packaged correctly on changes to layouts. I haven't yet narrowed it down closely enough to report a bug. Rebuilding the project fixes it.)

Final variables: Type an expression, then press ctrl-alt-v for "create a local variable to store the results of this expression." A little thought bubble appears containing a checkbox for "Declare final." Having checked that once, my created variables are now final by default. Hurray!

JetBrains supports the local user group community by giving free licenses to attendees (one random giveaway at each meeting of the St. Louis JUG when at least thirty people show up, which is most of the time). JetBrains also supplies licenses to leaders of the JUG. This is a great reason to be active in the local user group community!

Tuesday, December 13, 2011

Gradle is easy: Groovy tests

Today in Unit Testing, an evil framework class hid my important return value away in a private field.

Groovy to the rescue!

So far, all our code and tests are in Java. It took only two lines in build.gradle, as specified in the gradle documentation, and poof.

I put my little test class in src/test/groovy/package/structure, typed "gradle build" and wa-la! The results from the groovy test show up right along with the Java tests. Sweet.

class SomethingTest {
def email = "blah@blha.com";

UsefulClass usefulClass
CheckEmail subject

@Before
void setup() {
usefulClass = mock(UsefulClass.class);
subject = new Something(userService);
subject.setEmailAddress(email);
}

@Test
void falseWhenEmailFound() {
when(usefulClass.find(email)).thenReturn(new Thingie());

Reply<Boolean> result = subject.methodUnderTest();

assertEquals result.entity , Boolean.FALSE // see? that mean old private field is right there for the testing.
}

Git is hard: applying single commits to another branch

Want to apply just one commit from one branch into another branch? Don't merge -- that'll bring in all the commits behind the one you want.

The secret is:
git cherry-pick <commit name>


To find the commit name, you can "git log <branch-that-has-the-commit>"
To see the contents of the commit, you can "git show <commit name>"

Be in the branch you want to change (git checkout <branch>) and then use cherry-pick to bring in exactly the fixes you want.

Git is hard: amending commit history

If you're used to subversion and cvs, using git can be mind-bending. It does all the same things (and more), but nothing in quite the same way.

Idiomatic git means creating local branches, doing lots of little commits, then altering your local commit history if needed before pushing to the shared repository.

Today I tried to do that -- branched, made a bunch of little commits, branched again, committed one more, then.... oh crap. I created a branch but didn't check it out, so all those commits went to master.

Fortunately, I haven't pushed, so all those commits exist only in my local repository. I can screw with them.

To move your x most recent commits from master to a branch that you created a while back, but never checked out:

git checkout
git rebase master // this moves the branch pointer to where master is now

git checkout master
git reset --hard HEAD^x // this moves the master pointer back x commits.


Alternately, you can specify exactly which commit a new branch should include:

git rebase --onto <commit_name> <branch that has that commit> <branch that wants it>


For instance, I used "git log master" to find the last commit on master that I wanted my branch a236 to include, then did this:
git rebase --onto 8d819fed45753abaf05c59f4caee359804f28b47 master a236

Now branch a236 includes that commit. I'm free to reset master to something earlier, and the commits will be remembered by branch a236.

With all my commits and branches reorganized, I can push master to origin, leaving my personal branches local.

Just in this post I've used several concepts -- local repository, master, push, rebase, reset, origin -- foreign to Subversion users. And worse, I've used some concepts -- branch, checkout -- that sound familiar but subtly different.

Git and dvcs need to be learned from the inside out, at least a little bit, to be used with benefits and without frustration. The tutorials don't teach it this way. I'll make a presentation, and find some place to give it.