Passing a value in a where: block in Spock test - unit-testing

Is it possible to pass a value in where block like this.
I have tried this. But it fails and gives MissingPropertyException.
And I want the name1 and name2 to be inside the method.
def "length of names #name"() {
def name1 = "Spock"
def name2 = "Java"
expect:
name.size() == length
where:
name || length
name1 || 5
name2 || 2
}

Try this:
def "test length of names"() {
expect:
name.size() == length
where:
[name,length]<<getTestData()
}
def getTestData(){
[["Ram" ,3 ] ,["Test" ,4] ]
}
Hope that helps!!!
Thanks

Test data belongs in the where block, not hard coded in the test (feature) method.
One rough way to see this is to think of the test body (excluding the where block) as a method with some number of parameters -- 2 in your case, name and length. And then realize that the where clause just provides data values to the test runner to use when invoking your test method.
Spock uses Groovy magic to transform
def "test length of names"() {
expect:
name.size() == length
where:
name | length
"Spock" | 5
"Java" | 4
}
into something roughly like
def test_length_of_names(name, length) { // note the arguments
assert name.size() == length
}
and then tells the test runner to call the test once for each row in the where clause
test_length_of_names("Spock", 5)
test_length_of_names("Java", 4)
This approach
provides a nice separation of concerns between test logic and test data
allows relatively generic tests to be reused for a wide range of inputs and edge cases
avoids duplication in test code
supports a test design style that deserves the name data-driven testing.
This explanation leaves out a few details, such as creating an instance of the spec for each test, updating the name of each test invocation and calling the various setup and cleanup methods.
See the Spock documentation for more details.

Related

Dynamically change data in where clause using Spock

I have to iterate over some map and for every key, to make checks based on the current element,so I tried:
class TestSuite extends Specification {
#Shared
def elements
def setupSpec{
elements = ['a.txt':1,'b.txt':2]
}
#Unroll
def 'test for #first and #second'() {
expect:
true
where:
[first, second] << [elements.keySet(), elements[first].findResults { key, value->
key.substring(key.indexOf('.') + 1)
}].combinations()
}
}
but Spock fails and says that first is unknown.
How can I do that so that the two values to be in the name of the test so in unroll to see their values?
Edited
I have to say that your code does not make much sense. I have hesistated to just downvote your question instead of replying. There is so much wrong with this question. Just shows a lack of effort in formulating your question.
The first red flag is that you did not even try to compile this code. You have a map with String keys and integer values:
your map litteral does not compile. key/value pairs are separated by commas in groovy.
You call methods of this map that (Map#key() ?) are not in the API.
Then, there are two possibilities, either your imaginary key() method returns the key, which does not make any sense, because first IS the key already, or key() returns the value, which is really bad naming. But bad naming is not all, because then you call toUpperCase() on an integer.... This is a mess!
Nevertheless I am going to show you how you can base the value of a where variable on the value of another where variable, because that's the core part of your question, with
import spock.lang.*
class MyFirstSpec extends Specification {
//elements needs to be Shared to be used in a where block
#Shared
def elements = ['a':1,'b':2]
#Unroll
def 'test for #first and #second and #third'() {
expect:
true
where:
first << elements.keySet()
and:
second = elements[first]
third = first.toUpperCase()
}
}
​resulting in
- test for a and 1 and A
- test for b and 2 and B

Boolean Assert in ABAP Unit

How do I write a simple ABAP Unit Assert statement to check if any call, expression or other statement evaluates to true?
I can't see any basic assert() or assert_true() methods in CL_AUNIT_ASSERT while I'd expect those to be very common. I can approximate such an assert as follows, but is there no cleaner way?
cl_aunit_assert=>assert_equals(
act = boolc( lv_value > 100 OR lv_value < 2 )
exp = abap_true ).
cl_aunit_assert=>assert_equals(
act = mo_model->is_active )
exp = abap_true ).
Depending on your SAP NetWeaver stack you can (or should) use the updated ABAP Unit Class CL_ABAP_UNIT_ASSERT. This class is available at a Basis-Release >= 7.02. SAP declared this class as 'FINAL' so it´s impossible to inherit from it, but on the other side they added some ASSERT-Methods like the ASSERT_TRUE Method!
Here is a possible usage of this method:
cl_abap_unit_assert=>assert_true(
exporting
act = m_ref_foo->is_bar( l_some_var )
msg = 'is_bar Method fails with Input { l_some_var }'
).
For the releases I have access to, there's probably no shorter way than the one you outlined. You can create a subclass of CL_AUNIT_ASSERT and add your own static ASSERT_TRUE method. It's not a bad idea to do so and at the same time make your local ABAP Unit test class a subclass of that ZCL_AUNIT_ASSERT - this way, you can omit the cl_aunit_assert=> prefix which will save some keystrokes.
You cannot see such methods because there is no boolean type in ABAP.
While in Java, C++ or C, you are able to assign a result of a condition to a variable, like this
int i = 5;
boolean result = i > 3;
You cannot do the same thing in ABAP as there is no boolean type. Therefore what in other languages is a one liner, in ABAP it will always be more prolix.
DATA: i TYPE i VALUE 5.
DATA: result TYPE abap_bool.
IF i > 3.
result = abap_true.
ELSE.
result = abap_false.
ENDIF.
The thing you used seems to be a new feature, that has been recently added to the language and most of the customers will not be using for a long time. Also the CL_AUNIT_ASSERT class was created way before the new elements came to the language.
So right now, there is a possibility to write the above thing as one liner. However there is still no boolean type in the language.
DATA: i TYPE i VALUE 5.
DATA: result TYPE abap_bool.
result = boolc( i > 3 ).
On the other hand, there is no boolean type, but you could simply use ASSERT_INITIAL or ASSERT_NOT_INITIAL in this case, as boolean is emulated by either X (true) or space (false). The latter is an initial value in ABAP.
The cleanest way is to just fail:
if value > limit.
cl_abap_unit_assert=>fail( ).
endif.
Or a more informative:
cl_abap_unit=>fail( msg = 'Limit exceeded' ).

Spock - Ignoring a data driven entry

Say I have the sample data driven spec:
class DataDriven extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
[a,b,c] << runSomeSQL()
}
}
Is there a way to tell Spock to officially ignore (as a contrived example) where a < 7? EG as if I didn't use the data driven mechanism and simply #Ignore-ed the a < 7 cases
The only solution is to comment out the lines to be ignored.

What is better approach to testing pure functions?

I'm new to Haskell. I'm testing a simple function with Test.Framework:
import Test.Framework (defaultMain, testGroup)
import Test.Framework.Providers.HUnit
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck
import Test.HUnit
data Kind = Variable
| Const
| Polymorphic
deriving (Show, Eq, Ord)
calculate :: Int -> Kind -> Float
calculate quantity Variable =
(**2) . fromIntegral $ quantity
calculate _ Const =
10
calculate quantity Polymorphic =
if quantity <= 10 then
10
else
(**2) . fromIntegral $ quantity
prop_ValuePositive quantity kind =
calculate quantity kind
>= 0.0
test_ValueVariable1 =
calculate 1 Variable
#?= (**2) 1
test_ValueVariable2 =
calculate 10 Variable
#?= (**2) 10
test_ValueConst1 =
calculate 1 Const
#?= 10
test_ValueConst2 =
calculate 10 Const
#?= 10
test_ValuePolymorphic1 =
calculate 1 Polymorphic
#?= 10
test_ValuePolymorphic2 =
calculate 11 Polymorphic
#?= (**2) 11
instance Test.QuickCheck.Arbitrary Kind where
arbitrary = Test.QuickCheck.oneof(
[return Variable,
return Const,
return Polymorphic])
main = defaultMain tests
tests = [
testGroup "Value" [
testProperty "Value is positive" prop_ValuePositive,
testCase "Value is calculated right for Variable"
test_ValueVariable1,
testCase "Value is calculated right for Variable"
test_ValueVariable2,
testCase "Value is calculated right for Const"
test_ValueConst1,
testCase "Value is calculated right for Const"
test_ValueConst2,
testCase "Value is calculated right for Polymorphic"
test_ValuePolymorphic1,
testCase "Value is calculated right for Polymorphic"
test_ValuePolymorphic2
]
]
What bothers me is that it's recommended to test pure functions with QuickCheck properties and impure functions with HUnit test cases. But that way, I would have to just repeat the function definition for each of 3 cases (Const, Variable and Polymorphic) in properties to test that the function returns what it's supposed to. That is too much duplication in my opinion:
prop_ValueVariable quantity Variable =
calculate quantity Variable
== ((**2) . fromIntegral $ quantity)
(and so on for all the cases of Kind)
In contrast, in the current code I test only one "obvious" property of function and provide some "sample points" for what the function should return, without actually duplicating the definition (in spirit of unit testing).
What is right approach?
Use properties for testing of all aspects of this function and possibly duplicate its definition in tests
Use properties only for, well, "properties" of what should be returned, but don't duplicate the definition and provide just some unit tests
That property based testing is for pure code and unit tests for impure code is a useful guideline, but not an absolute truth. Unit tests can be useful for pure code, too. I usually start with a unit test, e.g.
describe "parseMarkdown" $ do
it "parses links" $ do
parseMarkdown "[foo](http://foo.com/)" `shouldBe` Link "http://foo.com" "foo"
and then later abstract it to a property
it "parses *arbitrary* links" $
property $ \link#(Link url name) ->
parseMarkdown "[" ++ name ++ "](" ++ url ++ ")" `shouldBe` link
But sometimes I just stick with the unit test because either (a) there is no good property or (b) a property does not increase the test coverage.
On the other hand properties can be useful for impure code, too. You e.g. may want to test your database abstraction with properties
describe "loadUser" $ do
it "retrieves saved users from the database" $ do
property $ \user -> do
saveUser user >>= loadUser `shouldReturn` user
No, of course you are not supposed to duplicate the definition in this way. What would be the point? You may as well simplify the test to prop_trivial q k = calculate q k == calculate q k. The only case when I'd consider it is when you plan to change the way function is calculated in the future and want to check that it still returns the same result.
But if your unit tests are created by just putting values into the function definition and seeing what comes out, they are also not particularly useful either, for the same reason.

How can I avoid over-testing with example

I've been trying to start testing my code more, and I thought I would mimic the style of some of the tests that were autogenerated for by me rails scaffolding (I'm using rspec and rails, but my question is really just general-tdd). However, those methods were very basic, along the lines of do something. then if foo, do something else. I feel like as soon as you get more complex by adding one more 2 more things to condition in your if, things start spiraling and you get nested examples all over the place. Here's an example of what i've been doing that feels like overkill.
First the method
def maybe_blah(foo)
if foo != nil && foos.find_by_id(foo.id) != nil
blah unless bar?(foo)
end
end
this method is pretty simple, here's how I was planning on testing it
describe maybe_blah
shared_examples "what happens when bad input is passed" do
it "doesn't call bar?"...
it "doesn't call blah"...
end
context "when foo is not nil"
context "when foo is in foos"
context "bar? returns true"
it "doesn't call blah" do
some code involving mocking bar? and blah
end
end
context "bar? returns false"
it "does call blah" do
some code involving mocking bar? and blah
end
end
end
context "when foo is not in foos"
include_examples "what happens when bad input is passed"
end
end
context "when foo is nil"
include_examples "what happens when bad input is passed"
end
end
That's noticeably shorter than what the test would be if there was all of the setup and whatever else in there (testing maybe_blah for real like that took me 55 lines), so you can see how it seems to get out of hand. Is there a good way of testing a method that does feel like such overkill.
I don't see a way around having 3-deep nesting when you have 3 conditions you're testing (at least without repeating yourself even more), but it seems like you'd need to do that to make sure you're handling all different cases. Also, it seems dumb to test the fail result for every different bad input, but how else would you know you're actually failing on those bad inputs?
So is this just overkill?
Actually you condition is the same as:
def maybe_blah(foo)
if foo != nil && foos.find_by_id(foo.id) != nil && !bar?(foo)
blah
end
end
Thus you can extract it into separate method using Decompose Conditional and Consolidate Conditional Expression techniques:
def maybe_blah(foo)
blah if can_do_it?(foo)
end
def can_do_it?(foo)
foo != nil && foos.find_by_id(foo.id) != nil && !bar?(foo)
end
After that you can test this method in two contexts
describe '#maybe_blah' do
context 'when can do' do
# stub can_do_it? and returns true
# stould receive :blah
end
context 'when cant do' do
# stub can_do_it? and returns false
# should not receive :blah
end
end
And test condition separately.
And you can omit != nil
def can_do_it?(foo)
foo && foos.find_by_id(foo.id) && !bar?(foo)
end