How to create new projects using an upcoming version of the Phoenix Framework? Right now, 1.3 is the current stable version that is released and when using mix phx.new the project it creates will use 1.3.
The upcoming version 1.4 is certainly stable enough to play around with, but how to create a new project using it? Here are the steps:
➤ mix archive.uninstall phx_new
Are you sure you want to uninstall /Users/steffen/.mix/archives/phx_new? [Yn]
➤ git clone https://github.com/phoenixframework/phoenix
➤ cd phoenix/installer
➤ MIX_ENV=prod mix do archive.build, archive.install
Compiling 10 files (.ex)
Generated phx_new app
Generated archive "phx_new-1.4.0-dev.ez" with MIX_ENV=prod
Are you sure you want to install "phx_new-1.4.0-dev.ez"? [Yn]
* creating /Users/steffen/.mix/archives/phx_new-1.4.0-dev
Creating a new project with the development version of phoenix:
➤ mix phx.new asdf
➤ cat asdf/mix.exs
...
defp deps do
[
{:phoenix, github: "phoenixframework/phoenix", override: true},
{:phoenix_pubsub, "~> 1.1"},
{:phoenix_ecto, "~> 3.2"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
{:cowboy, "~> 1.0"}
]
end
...
Bytes don't hurt
Freitag, 7. September 2018
Donnerstag, 26. Februar 2015
Using Mockito on Android
There are a few obstacles when trying to use Mockito on Android. However, they can be overcome easily:
0) Adding Mockito dependency to project:
Add this to your setUp() or beforeClass() methods in the test class:
androidTestCompile 'org.mockito:mockito-core:2.+'1) Yields VerifyError exception:
java.lang.VerifyError: org/mockito/cglib/core/ReflectUtils at org.mockito.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:167) at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217) at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145) at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117) at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109) at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105) at org.mockito.cglib.proxy.Enhancer.Solution is adding the following dependency next to mockito:(Enhancer.java:70) at org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:99) at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:61) at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:53) at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24) at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33) at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59) at org.mockito.Mockito.mock(Mockito.java:1284) at org.mockito.Mockito.mock(Mockito.java:1162) at MyTest.java at java.lang.reflect.Method.invokeNative(Native Method) at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214) at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199) at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176) at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'2) Yields another exception:
java.lang.IllegalArgumentException: dexcache == null (and no default could be found; consider setting the 'dexmaker.dexcache' system property) at com.google.dexmaker.DexMaker.generateAndLoad(DexMaker.java:359) at com.google.dexmaker.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:258) at com.google.dexmaker.mockito.DexmakerMockMaker.createMock(DexmakerMockMaker.java:55) at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33) at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59) at org.mockito.Mockito.mock(Mockito.java:1284) at org.mockito.Mockito.mock(Mockito.java:1162) at MyTest.java at java.lang.reflect.Method.invokeNative(Native Method) at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214) at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199) at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176) at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)See here: http://code.google.com/p/dexmaker/issues/detail?id=2
Add this to your setUp() or beforeClass() methods in the test class:
System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath());
Freitag, 21. November 2014
Couchbase: set document owner in sync function using requireUser
Couchbase's sync function is the central point where you can manage access rights of the documents in the database. In addition to the new and old document it used to receive a userContext as a third parameter that could be used to retrieve the currently logged in user name. This parameter was removed because a current user is not available in all the situations where the sync function gets invoked by Couchbase.
However, a common usecase is to set the currently logged in user as the owner of the document, for example to make sure only he can edit it. How do you achieve giving ownership of a document to the current user then? If you store the owner in doc.creator, then in your sync function, you can make sure the currently logged in user matches that by invoking requireUser(doc.creator);
After having verified doc.creator by this call, you can use it to set up your access model, for instance by setting the channel for the document.
Relevant post from the mailing list for more details.
However, a common usecase is to set the currently logged in user as the owner of the document, for example to make sure only he can edit it. How do you achieve giving ownership of a document to the current user then? If you store the owner in doc.creator, then in your sync function, you can make sure the currently logged in user matches that by invoking requireUser(doc.creator);
After having verified doc.creator by this call, you can use it to set up your access model, for instance by setting the channel for the document.
Relevant post from the mailing list for more details.
Mittwoch, 3. September 2014
MacPorts and installing Ruby's mysql gem
MySQL 5.5 client and server is installed using MacPorts.
When trying to install the mysql2-gem, it will fail as follows:
$ sudo gem install mysql2 -v '0.3.16' Building native extensions. This could take a while... ERROR: Error installing mysql2: ERROR: Failed to build gem native extension. /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby extconf.rb checking for ruby/thread.h... yes checking for rb_thread_call_without_gvl() in ruby/thread.h... yes checking for rb_thread_blocking_region()... yes checking for rb_wait_for_single_fd()... yes checking for rb_hash_dup()... yes checking for rb_intern3()... yes checking for mysql_query() in -lmysqlclient... no checking for main() in -lm... yes checking for mysql_query() in -lmysqlclient... no checking for main() in -lz... yes checking for mysql_query() in -lmysqlclient... no checking for main() in -lsocket... no checking for mysql_query() in -lmysqlclient... no checking for main() in -lnsl... no checking for mysql_query() in -lmysqlclient... no checking for main() in -lmygcc... no checking for mysql_query() in -lmysqlclient... no *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options.It seems like it has trouble locating the mysqlclient. A quick search in /opt discovered /opt/local/lib/mysql55/bin/mysql_config. mysql_config will help gem to find the mysql libraries:
$ sudo gem install mysql2 -v '0.3.16' -- --with-mysql-config=/opt/local/lib/mysql55/bin/mysql_config Building native extensions with: '--with-mysql-config=/opt/local/lib/mysql55/bin/mysql_config' This could take a while... Successfully installed mysql2-0.3.16 Parsing documentation for mysql2-0.3.16 unable to convert "\xCA" from ASCII-8BIT to UTF-8 for lib/mysql2/mysql2.bundle, skipping Installing ri documentation for mysql2-0.3.16 1 gem installedVoila.
Freitag, 9. Mai 2014
Disable horizontal scrolling for ViewPager
Depending on the state of your application it might become necessary to make your ViewPager not scroll horizontally when the user makes a swiping gesture. One use case for this is displaying multiple images in a ViewPager that can be zoomed into and you want the user only to be able to swipe to the next image when it is fully zoomed out. Swiping gestures that are carried out when having zoomed into the image should pan the image contents and not switch to the next one.
There is an elegant way to achieve this behaviour by overriding canScroll() in ViewPager. Here's how to disable horizontal swiping temporarily:
public class GalleryViewPager extends ViewPager { ... @Override protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { GalleryImage image = getImage(); if(image.isZoomed()) { /* the child view of the ViewPager can scroll, so the ViewPager would not change page */ return true; } else { /* let base class decide what to do */ return super.canScroll(v, checkV, dx, x, y); } } ... }By returning true from canScroll() we indicate that the child view of the ViewPager itself can scroll, so the ViewPager will not change to the next page, effectively disabling horizontal scrolling for the ViewPager.
Dienstag, 25. Februar 2014
Attaching debugger when running Robolectric tests from Android Studio
The Gradle View (View → Tool Windows → Gradle) in Android Studio allows you to easily run your unit tests from within Android Studio. From the tree of tasks for your project, just select the task test and run it.
It's also possible to attach the debugger to that process executing your Robolectric tests by simply choosing Debug instead of Run. However, you might face this error:
It's also possible to attach the debugger to that process executing your Robolectric tests by simply choosing Debug instead of Run. However, you might face this error:
Error running android-app:appname [test]: Unable to open debugger port : java.net.SocketException "Socket closed"In order for the debugger to attach you need to uncheck "Use in-process build" in the settings menu for Android Studio under Compiler → Gradle.
Freitag, 17. Januar 2014
Getting started with Robolectric and Gradle in Android Studio
Unit tests are an invaluable tool to ensure software behaves the way it is supposed to which you want to check as often as possible while developing. However, running tests on an Android emulator is slow. Robolectric is a unit test framework that enables you to run your Android unit tests as plain vanilla JUnit tests inside the JVM on your computer, which is much faster and less cumbersome than to run them inside the emulator.
This is because Android Studio expects test code to be in src/instrumentationTest, but luckily we can change that in build.gradle:
New Android projects are built with Gradle
There is a plugin for Gradle called gradle-android-test-plugin that will run unit tests relying on Robolectric and compile the results in a test report. The following will describe how to change your build.gradle to set this up. First, pitfalls along the way will be shown, followed by a working build.gradle configuration. Finally, a few tweaks have to be made to integrate this properly with Android Studio.Pitfalls and how to work around them
These are problems I encountered when trying to set up the gradle-android-test-plugin and how to circumvent them.Gradle cannot determine dependencies
* What went wrong: Could not determine the dependencies of task ':MyApp:testDefaultFlavorDebug'. > A base directory must be specified in the task or via a method argumentSolution: Use 0.9.1-SNAPSHOT version of the gradle-android-test-plugin., it fixes this problem.
Robolectric: Resource path restrictions
java.lang.IllegalArgumentException: Resource path must end in "/res" at org.robolectric.res.PackageResourceLoader.<init>(PackageResourceLoader.java:20) at org.robolectric.res.PackageResourceLoader.<init>(PackageResourceLoader.java:11)Solution: Use 2.3-SNAPSHOT version of Robolectric, it fixes this restriction on the path name.
Robolectric: No KitKat
java.lang.UnsupportedOperationException: Robolectric does not support API level 19, sorry!Solution: As defined per SdkConfig.java, Roboelectric only supports SDKs 16 through 18. Change targetSdkVersion to 16, 17 or 18.
Summary of necessary changes to build.gradle
Your build.gradle has to be changed in quite a few places to set up gradle-android-test-plugin. Here's the condensed summary of theses changes:buildscript { repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } } dependencies { classpath 'com.squareup.gradle:gradle-android-test-plugin:0.9.1-SNAPSHOT' } } apply plugin: 'android-test' repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } } dependencies { testCompile 'junit:junit:4.10' testCompile 'org.robolectric:robolectric:2.3-SNAPSHOT' testCompile 'com.squareup:fest-android:1.0.+' }
Write a first unit test
Now you can create a unit test. Create a file in src/test/com.myapp.MyTest.java:package com.myapp; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import static org.junit.Assert.assertTrue; @RunWith(RobolectricTestRunner.class) public class MyTest { @Test public void testNumberOne() { assertTrue(false); } }Note that with Robolectric 2.3-SNAPSHOT you do not need RobolectricGradleTestRunner anymore, since it is integrated. When you now run ./gradlew test in your project, it should run that very unit test, which will -- by design -- fail:
com.myapp.MyTest > testNumberOne FAILED java.lang.AssertionError at MyTest.java:13
Integrating with Android Studio
So far, we have a working set up of Gradle, Robolectric and the gradle-android-test-plugin -- but only for the console. When we try to "Sync Project with Gradle Files" in Android Studio, the IDE will not pick up our newly created src/test folder and it will not provide content assist when writing code.This is because Android Studio expects test code to be in src/instrumentationTest, but luckily we can change that in build.gradle:
android { sourceSets.instrumentTest.setRoot('src/test') }Android Studio also cannot compile the test code because it misses dependencies. This is because it expects these dependencies to be defined in the configuration named instrumentTestCompile, whereas currently, we are using the testCompile configuration only. We have to add the dependencies defined earlier to the configuration Android Studio uses. This can even be achieved without repeating them, but by creating a copy, like so:
dependencies { instrumentTestCompile configurations.testCompile.dependencies }
Summary
This article described how to overcome the problems when adding the gradle-android-test-plugin to a project. It provided a configuration for Gradle to run a sample unit test leveraging the Roboelectric library. In the last step, it showed how to alter the configuration so that Android Studio would play along.
Abonnieren
Posts (Atom)