I want to validate text inputs with a helper class. I started with a method to prove for a single name with upper case at the beginning and max length of 20 characters:
package xyz.helper;
import java.util.regex.Pattern;
public abstract class InputValidator {
public static boolean checkSingleName(String string) {
return Pattern.matches("^[A-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜ]{1}[a-zàáâãäåæçèéêëìíîïñòóôõöøùúûü]{1,19}", string);
}
}
When I test in the Activity for example with "Hello", I get back FALSE and the error message. Is my regular expression wrong?
// Check User entries
private boolean checkEntries() {
boolean validEntry = InputValidator.checkSingleName(title.toString());
if (!validEntry) {
title.setError(getString(R.string.error_occasion));
return false;
}
return true;
}
Thanks for any hints
I think the way you've built the sentence is not right currently. I'd try this way:
return Pattern.compile("^[A-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜ]{1}[a-zàáâãäåæçèéêëìíîïñòóôõöøùúûü]{1,19}").matcher("Hello").matches()
Often, in questions like this, it is what you are NOT showing that is the problem.
Demonstration of a working Java implementation of your regex (see http://ideone.com/nFPcic):
import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.regex.Pattern;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
if(checkSingleName("Hello")) {
System.out.println("Yes that is valid");
}
else {
System.out.println("No that is not valid");
}// your code goes here
}
public static boolean checkSingleName(String string) {
return Pattern.matches("^[A-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜ]{1}[a-zàáâãäåæçèéêëìíîïñòóôõöøùúûü]{1,19}", string);
}
}
This prints out "Yes that is valid" with "Hello" as the input string. When I add a digit to the name, it prints "Not that is not valid". As expected.
If you are getting a different result, it is because of something you are not showing. Could it be there is a carriage return, space or tab at the start/end of the string you are testing?
Incidentally, you really don't need the {1} after the initial capital letter; and your regex is terribly restrictive. See http://en.wikipedia.org/wiki/Category:Lowercase_proper_names_or_pseudonyms , or even better, http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/ - thought provoking and at times hilarious.
Related
When using android.util.ArraySet in code, I cannot test the classes using it in my non-android test classes, because it would throw an exception:
java.lang.RuntimeException: Method add in android.util.ArraySet not mocked. See http://g.co/androidstudio/not-mocked for details.
The link says:
This is to make sure your unit tests only test your code and do not depend on any particular behaviour of the Android platform (that you have not explicitly mocked e.g. using Mockito)
How can I unit test code using ArraySet? I would say somehow mocking (Mockito, PowerMock) it by somehow "replacing it with a HashSet" could be promising:
Code to be tested:
Set<Bird> birds = new ArraySet<>();
birds.add(currentBird);
Test code:
whenNew(ArraySet.class).withAnyArguments().thenAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return new HashSet();
}
});
This gives java.lang.ClassCastException: java.util.HashSet cannot be cast to android.util.ArraySet.
A workaround would be to not to return a HashSet but some MyFakeArraySet extends ArraySet (which internally uses a HashSet), but sadly ArraySet is final. :-(
you should not use android sdk classes in your non-android test classes.
but if you want , you can use something like this :
#Test
public void testArraySet() {
final Set<Bird> fakeBirds = new HashSet<>();
ArraySet<Bird> birds = (ArraySet<Bird>) Mockito.mock(ArraySet.class);
when(birds.add(any(Bird.class))).then(new Answer<Boolean>() {
#Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
Bird param = invocation.getArgument(0);
return fakeBirds.add(param);
}
});
when(birds.contains(any(Bird.class))).then(new Answer<Boolean>() {
#Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
Bird param = invocation.getArgument(0);
return fakeBirds.contains(param);
}
});
Bird bird = new Bird();
birds.add(bird);
assert birds.contains(bird);
}
I've found out that the classes in the test folders seem to have precedence. So I do not have to mock anything. I can just place a package android.util into my test folders and an ArraySet class completely specified by me:
package android.util;
import android.support.annotation.NonNull;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class ArraySet<E extends Object> implements Collection<E>, Set<E> {
private final HashSet<E> HASH_SET;
public ArraySet(int capacity) {
Log.e("ArraySet", "WARNING, using fake array set!");
HASH_SET = new HashSet<>(capacity);
}
#Override
public int size() {
return HASH_SET.size();
}
// Do this with all other methods as well: Chain them into HASH_SET.
}
package edetect.webiscr.cf.e_bookgeneral;
import android.app.ActivityManager;
public class ApplockHandler {
String appg = "com.example.lock";
ActivityManager.killBackgroundProcesses(String appg);
}
The error results to expected
ActivityManager.killBackgroundProcesses(String appg);
I'm pretty new to java and android.. So sorry for my noobishness
Would appreciate any help :)
You need to put killBackgroundProcess into a function, and only pass in appg without the String datatype in front of it. For example:
package edetect.webiscr.cf.e_bookgeneral;
import android.app.ActivityManager;
public class ApplockHandler {
private final String appg = "com.example.lock";
public ApplockHandler() {}
public void killLock() {
ActivityManager.killBackgroundProcesses(appg);
}
}
Call killBackgroundProcesses from any function. Also you need to get an instance of ActivityManager.
public class ApplockHandler {
public ApplockHandler() {}
public void killLock(String appg) {
ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
am.killBackgroundProcesses(appg);
}
}
Now call this killLock method from anywhere by passing the package name.
I'm using Green Coffee library to run Cucumber scenarios in my instrumentation tests. I followed example provided by repo step-by-step, but here's the error:
junit.framework.AssertionFailedError: Class pi.survey.features.MembersFeatureTest has no public constructor TestCase(String name) or TestCase()
And when I try to add default constructor to the class like provided here, it says
no default constructor available in
'com.mauriciotogneri.greencoffee.GreenCoffeeTest'
Here's my test's source code:
package pi.survey.features;
import android.support.test.rule.ActivityTestRule;
import com.mauriciotogneri.greencoffee.GreenCoffeeConfig;
import com.mauriciotogneri.greencoffee.GreenCoffeeTest;
import com.mauriciotogneri.greencoffee.Scenario;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.IOException;
import pi.survey.MainActivity;
import pi.survey.steps.memberSteps;
#RunWith(Parameterized.class)
public class MembersFeatureTest extends GreenCoffeeTest {
#Rule
public ActivityTestRule<MainActivity> activity = new ActivityTestRule<>(MainActivity.class);
public MembersFeatureTest(Scenario scenario) {
super(scenario);
}
#Parameterized.Parameters
public static Iterable<Scenario> scenarios() throws IOException {
return new GreenCoffeeConfig()
.withFeatureFromAssets("assets/members.feature")
.scenarios();
}
#Test
public void test() {
start(new memberSteps());
}
}
And my members.feature source:
Feature: Inserting info to server
Scenario: Invalid members
When I introduce an invalid members
And I press the login button
Then I see an error message saying 'Invalid members'
Regarding the questions about the constructors. Due to the fact that tests in GreenCoffee require:
#RunWith(Parameterized.class)
The static method annotated with #Parameters must return a list of something (but not necessarily Scenario). The examples in the documentation simply return a list of scenarios, that's why the constructor must take a single Scenario as a parameter.
However, you can create a class that encapsulates the scenario and other objects that you may need to pass to the constructor. For example, given the following class:
public class TestParameters
{
public final String name;
public final Scenario scenario;
public TestParameters(String name, Scenario scenario)
{
this.name = name;
this.scenario = scenario;
}
}
You can write:
public TestConstructor(TestParameters testParameters)
{
super(testParameters.scenario);
}
#Parameters
public static Iterable<TestParameters> parameters() throws IOException
{
List<TestParameters> testParametersList = new ArrayList<>();
List<Scenario> scenarios = new GreenCoffeeConfig()
.withFeatureFromAssets("...")
.scenarios();
for (Scenario scenario : scenarios)
{
testParametersList.add(new TestParameters(scenario.name(), scenario));
}
return testParametersList;
}
In this way you can receive multiple values (encapsulated in an object) in the test constructor.
Solved problem by just fixing the structure.
code details in this commit
I want to create a custom annotation which when used on a method, will check if a certain static variable is valid. If not will throw an exception.
e.g:
#IDCheck
public void someMethod() {
//code...
}
Which checks for an ID, stored as a global variable. It should not be null and the value must comply with some rules.
Since this ID keeps changing at runtime, I want to validate it using an annotation at runtime.
What I tried:
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Checks for a valid ID.
* <p>
* This is a marker annotation and it has no specific attributes.
*/
#Target(METHOD)
#Retention(RUNTIME)
public #interface IDCheck {
}
I am not sure how I can do a validation at runtime whenever a method with #IDCheck annotation is invoked.
Tried something like this:
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;
import javax.lang.model.SourceVersion;
#SupportedAnnotationTypes("IDCheck")
public class IDCheckProcessor extends AbstractProcessor {
#Override
public boolean process(Set<? extends TypeElement> arg0,
RoundEnvironment roundEnv) {
if(!Util.isIDValid()){
//Throw an exception.
return true;
}
return false;
}
#Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}
But that code in the process method never gets called.
If you want to check this at runtime, it is not necessary to use an annotation processor.
I recommend you use a proxy and a little reflection to make it happen. You have already defined your annotation. What you need to do is create an interface for the component you want to check and annotate the method declaration there.
public interface MyInterface {
#IDCheck
void someMethod();
}
Then you use Java's dynamic proxy to create a proxy of the interface:
MyInterface instance = Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
new Class[]{MyInterface}, handler);
The third parameter is the important thing here - this is an InvocationHandler. It will get notified each time a method from the proxy has been called. You should override it's invoke() method and implement your validation there. Something like this:
#Override
public Object invoke(Object proxy, Method method, Object[] args) {
if (method.isAnnotationPresent(IDCheck.class)) {
//proceed with navigation and throw exception if invalid
}
// delegate the method execution to a wrapped implementor of the MyInterface
}
This is guaranteed to work at runtime. The performance impact is not very big and it is unlikely it is even noticeable.
I am wondering if there is a syntax to print out something in the eclipse console windows. This is just like NSLog in xcode. Thank you
Use the android.util.Log class http://developer.android.com/reference/android/util/Log.html.
For example:
import android.util.Log;
class Someclass {
private static final String TAG = "Someclass";
...
public boolean someMethod(int argument) {
Log.i(TAG, "This is some information log");
if (argument == 0) {
Log.e(TAG, "Error argument is 0!!!");
return false;
}
Log.w(TAG, "Warning returning default value");
return true;
}
};
The reason the TAG variable is assigned like that instead of something like:
Somelcass.class.getSimpleName() is because the reflective method will cause the reflection metta data of the class to be loaded on initialisation, however, the 'preferred' method by android developers prevents that and hence saves CPU and initialisation time.
Take a look at the Log class - it has a number of different logging functions.