Some tests are used with this annotation #RunWith(Theories.class) in JUnit and I don't know when and why we use it?
You should use them when you would like your tests to focus on the generalized relationship between inputs and outputs. See: https://blogs.oracle.com/jacobc/entry/junit_theories.
I think capturing multiple types of input are one thing. The high level idea is that you want to test if your method is true for all possible inputs.
For example, let's say I have some complex business process that takes 5 different inputs, and let's say for each input, there's 10 possible states, so we end up with 10*10*10*10*10 = 100,000 possible input states, which means we need to know beforehand what all these 100,000 output values are.
However, you probably realize that you don't need to actually enumerate all 100,000 states. There's probably a subset that you are interested in. Let's theorize for example:
"Admins have no permission restriction". And if I wanted to assert that this is true, my Test ends up looking like the pseudo-code below.
#Test
public void AdminsHaveNoPermissionRestriction(User user, BusinessProcess bp, Input a, Input b ...) {
Assume.assumeThat("User is an admin", user.hasRole(admin);
// .. rest of test which uses bp, a, b etc...
)
The nice thing is that we skip un-interested objects (non-admins) because it fails the assumptions.
Related
In my code, I have to assert one value against 2 fields. This is what I have to do :
assertThat(request.get(0).name()).isEqualTo("ABC");
assertThat(request.get(0).name2()).isEqualTo("ABC");
How can I use one single line assertion for the above 2 lines?
For example to explain more what I need :
Is there a way I can achieve something like :
assertThat(request.get(0).name() && request.get(0).name2()).isEqualTo("ABC");
How can I use one single line assertion for the above 2 lines?
Why do you want to do such a thing ?
By trying to try too clever, you will get two drawbacks :
you will make your test more complex to read and to maintain.
you will lose the relevant feedback information as a test fails
Actually your test is fine.
If any of these two values doesn't respect the assertion, you have the exact line that spots the issue and you also have a relevant information message.
As a hint, you could maybe just remove the duplication :
final String expected = "ABC";
assertThat(request.get(0).name()).isEqualTo(expected);
assertThat(request.get(0).name2()).isEqualTo(expected);
I don't want to say that it is bad to make multiple assertions in a same statement. Not at all.
I say only that you have to adapt your way of asserting to the tools you are using.
And about it, you don't specify the matcher tool.
If the matcher tool provides a support to make this kind of assertion, use it.
Otherwise, don't make it in a raw way otherwise you will lose the benefit of getting useful failure test messages.
Here is an example with AssertJ that provides this feature out of box.
#Test
void namesEquals() {
List<Request> requests = new ArrayList<>();
requests.add(new Request("ABC", "ABD"));
Assertions.assertThat(requests.get(0)).extracting(Request::name, Request::name2)
.containsExactly("ABC", "ABC");
}
And in this failing test, you will get a useful information message :
java.lang.AssertionError:
Expecting:
<["ABC", "ABD"]>
to contain exactly (and in same order):
<["ABC", "ABC"]>
but some elements were not found:
<[]>
and others were not expected:
<["ABD"]>
A bit too clever perhaps, but you can try this:
assertTrue(Stream.of(request.get(0).name(), request.get(0).name2())
.allMatch("ABC"::equals));
Or you can give this a spin:
assertThat(Arrays.asList(request.get(0).name(), request.get(0).name2()),
Every.everyItem(IsEqual.equalTo("ABC")));
something like:
assertThat(request.get(0).name().equals( request.get(0).name2()) ?
request.get(0).name() : "false").isEqualTo("ABC");
I have a loop in my code which goes over a set of strings. Said strings are then passed along to several other functions.
In my tests, I'm basically emulating the flow of code and asserting at the start of each method I expect it to visit, if the string is correct.
But I can only write the test method once. Meaning that I have to do the following to catch all the different strings:
assertTrue(string.equals("test1") || string.equals("test2") || string.equals("test3") || ...);
However, there's a problem with this if one or more of those strings are not successfully passed to the list that is looped over. Since this is a chain of OR statements, it will succeed as long as there is 1 correct string, regardless of whether any of the other strings are missing. Which is a problem.
I can't emulate the loop, I can only emulate the functions receiving the data each time.
Is there a way to deal with this problem?
EDIT: some clarification.
I start out with a list of strings.
This list gets looped over, meaning every single string instance will go through a bunch of functions. And then the next string. And so on.
In the test, I can write dummies for the methods the string goes through. This means I override the behavior of the actual code and send my own custom return. This has to be correct though, since the function following that has to properly process what I just send to it.
But, when I start the test with the dummy data, it will do the loop, meaning the same function gets called multiple times, each time with a different string. I can't just do 1 test for one of the strings, because the next loop will fail on the next string.
I'm working on implementing probablistic matching for person record searching. As part of this, I plan to have blocking performed before any scoring is done. Currently, there are a lot of good options for transforming strings so that they can be stored and then searched for, with similar strings matching each other (things like soundex, metaphone, etc).
However, I've struggled to find something similar for purely numeric values. For example, it would be nice to be able to block on a social security number and not have numbers that are off or have transposed digits be removed from the results. 123456789 should have blocking results for 123456780 or 213456789.
Now, there are certainly ways to simply compare two numerical values to determine how similar they are, but what could I do when there are million of numbers in the database? It's obviously impractical to compare them all (and that would certainly invalidate the point of blocking).
What would be nice would be something where those three SSNs above could somehow be transformed into some other value that would be stored. Purely for example, imagine those three numbers ended up as AAABBCCC after this magical transformation. However, something like 987654321 would be ZZZYYYYXX and 123547698 would be AAABCCBC or something like that.
So, my question is, is there a good transformation for numeric values like there exists for alphabetical values? Or, is there some other approach that might make sense (besides some highly complex or low performing SQL or logic)?
The first thing to realize is that social security numbers are basically strings of digits. You really want to treat them like you would strings rather than numbers.
The second thing to realize is that your blocking function maps from a record to a list of strings that identify comparison worthy sets of items.
Here is some Python code to get you started. (I know you asked for Java, but I think the Python is clear and you aren't paying me enough to write it in Java :P ). The basic idea is to take your input record, simulate roughing it up in multiple ways (to get your blocking keys), and then group on by any match on those blocking keys.
import itertools
def transpositions(s):
for pos in range(len(s) - 1):
yield s[:pos] + s[pos + 1] + s[pos] + s[pos + 2:]
def substitutions(s):
for pos in range(len(s)):
yield s[:pos] + '*' + s[pos+1:]
def all_blocks(s):
return itertools.chain([s], transpositions(s), substitutions(s))
def are_blocked_candidates(s1, s2):
return bool(set(all_blocks(s1)) & set(all_blocks(s2)))
assert not are_blocked_candidates('1234', '5555')
assert are_blocked_candidates('1234', '1239')
assert are_blocked_candidates('1234', '2134')
assert not are_blocked_candidates('1234', '1255')
I am not looking for the answer to this question but just a brief outline of how to do it. This is a question from a exam past paper.
It states: Describe in English a sequence of tests that you might use to test code to implement the NumberCoversion class. Your tests should cover all the conditions described in the above definition.
I won't write the specification of the class but it contains things like: it must take String as input and output, accepting two parameters and returning null if a number is not valid etc.
The question is worth 10% so will I just be required to write a series of things like: Ensure that the constructor only accepts two parameters of type int, and not anything else e.g. double or accept 3 parameters.
Would it be worth writing possible JUnit test methods in English/Pseudocode.
Would this be the right sort of thing to write for tests in English?
I think the goal is to describe a test case which checks each of the specifications in the question, whilst also avoiding attempting to test things which are limited by the language construct (e.g. wrong number/type of arguments).
Describe in English what you will do if you write tests. Typically it's usage of the NumberConversion class.
According to the question, you need to describe tests in English. I think that jumping to JUnit unit tests is more than being asked for. If I answered this question, I would start by looking at the definition given of the NumberConversion class. I would describe tests that use valid inputs as well as tests that use invalid ones. For each test describe how you will ensure that the NumberConversion class behaves as expected, including expected error conditions.
As an example for what might be appropriate...
If the specifications were:
Takes a string as input
The string can be an arbitrarily large non-negative integer
If the string is not a non-negative integer, an exception is thrown
Then I would probably answer something along the lines of:
I would test with "42" as input to check that the method works with a "normal" number
I would test with "0" as input to check that the method works with the edge case number
I would test with "9223372036854775808" (1 more than Long.MAX_VALUE) as input to check that the method works with a number larger than the fixed length integers provided by Java
I would test with "-1" as input and ensure that an exception is thrown, as negative input is invalid
I would test witht "0xa" as input and ensure that an exception is thrown, as hexadecimal input is invalid
I would test witht "0.1" as input and ensure that an exception is thrown, as non integral input is invalid
I have a question which is described below:
What problems would arise for testing a Java class which counts number of words in a file?
The function's signature is below:
public int wordCount(String filename)
Well, this is a junit testing question.
If you know the problem, what is the solution of that?
So your question is what to test for? If yes, I'd say you should check if the definition of "word" is implemented correctly (e.g. is "stack-overflow" one word or two), are new lines handled correctly, are numbers counted as words (e.g. difference between "8" and "eight"), are (groups of special) characters (e.g. a hyphen) counted correctly.
Additionally, you should test whether the method returns the expected value (or exception) if the file does not exist.
This should be a good starting point.
To sfussenegger's list, I'd add the file handling checks: does the method respond correctly to files not found (including null filename), or lacking read permission?
Also, to sfussenegger's correctness list, I'd add whether duplicates count and case sensitivity rules, as well.
Of course, all of this requires that you know how the method is supposed to behave for all of these specifics. It's easy to tell someone to "go count words", but there are subtleties to that assignment.
Which is one of the big benefits of writing a good set of unit tests.
This really sounds like a task for FIT: Framework for Integrated Test. It's an acceptance testing framework that works with ant and JUnit.
One docent of mine did such a task and used this framework. It allows you to write a whole bunch of test cases within one html/wiki table. FIT will interpret each line as a parameter set for the function under test and checks the output.
For example:
This table displays the result of three test cases. Two passed, one failed.
You can use fit if you write sentences and define the number of words in your table. With FIT, they're executed and the result is displayed in a new table.
For further information, please read Introduction to FIT.