Cyclic parametrized test in a class with "class" scoped parameters - pytest

I have the following code:
#pytest.mark.parametrize('y', y_list, scope='class')
#pytest.mark.parametrize('x', x_list, scope='class')
class TestSomething:
def test_a(self, x, y):
pass
#pytest.mark.parametrize('z', z_list)
def test_b(self, x, y, z):
pass
def test_c(self, x, y):
pass
Order:
test_a[x1-y1]
test_b[x1-y1-c1]
test_c[x1-y1]
test_a[x2-y1]
test_b[x2-y1-c1]
test_c[x2-y1]
test_b[x1-y1-c2] <--- order issue
test_b[x2-y1-c2] <--- order issue
Expected order:
test_a[x1-y1]
test_b[x1-y1-c1]
test_b[x1-y1-c2]
test_c[x1-y1]
test_a[x2-y1]
test_b[x2-y1-c1]
test_b[x2-y1-c2]
test_c[x2-y1]
As you can see above, the expectation is that the test will run cyclically on a parameter designated for it and only then it will continue with the rest of the tests in the class.
Why is there disorder? And is there a solution to this? what am I missing?

Related

Passing arguments to instantiate object in Pytest

I have a class which I would like to instantiate using different sets of input parameters, comparing a property on the resultant object to a passed in value.
I am using the indirect flag on #pytest.fixture for the arguments which are sent to the class constructor. I am trying to unpack kwargs in the constructor. Unsuccesfully. This is the error:
TypeError: type object argument after ** must be a mapping, not SubRequest
Code:
import pytest
class MyClass:
def __init__(self, a):
self.a = a
#pytest.fixture
def my_object(request):
yield MyClass(**request)
# first element = arguments to MyClass, second element = value to compare test to
TEST_CASES = [({"a":1}, 1)]
#pytest.mark.parametrize("test, expected", TEST_CASES, indirect=["test"])
def test_1(my_object, test, expected):
assert my_object.a == expected
My goal is to have the object arguments and their test value TEST_CASES in one structure for easy inspection
I've suggest you a working example. Problem was in test code design. The parameter indirect should be True. Indirect parametrization with multiple fixtures should be done as described in docs. And fixture got all params in his request.param attribute.
import pytest
class MyClass:
def __init__(self, a):
self.a = a
#pytest.yield_fixture
def test_case(request):
params, expected = request.param
yield MyClass(**params), expected
# first element = arguments to MyClass, second element = value to compare test to
TEST_CASES = [({"a": 1}, 1)]
#pytest.mark.parametrize("test_case", TEST_CASES, indirect=True)
def test_1(test_case):
my_object, expected = test_case
assert my_object.a == expected

Shapeless and gremlin scala: How do I return the result of a call to `as`?

So, I am calling this function as (from gremlin-scala):
case class GremlinScala[End, Labels <: HList](traversal: GraphTraversal[_, End]) {
def as(name: String, moreNames: String*)(implicit p: Prepend[Labels, End :: HNil]) =
GremlinScala[End, p.Out](traversal.as(name, moreNames: _*))
}
It is defined here: https://github.com/mpollmeier/gremlin-scala/blob/master/gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala#L239
It takes an implicit Prepend argument, which I am not sure I understand. I know that gremlin-scala uses its HList to keep track of which points in the query as is called, so that later when select is called it knows which points in the traversal to return.
This is the key: as appends to that HList. Or prepends apparently, as the case may be.
This works fine in general code, but now I want to write a function that calls as and returns its result. This is where I am stuck: what is the signature of the return value of this function?
Finally, I have added an implicit param to my function, but I fear I have just chased the problem up a level. Here is what I have so far:
case class AsOperation[A, In <: HList](step: String) extends Operation {
def operate(g: GremlinScala[A, In]) (implicit p: Prepend[In, ::[A, HNil]]): GremlinScala[A, p.Out] = {
g.as(step)
}
}
This makes it compile, but I still can't use this function! Whenever I call it, it complains to me that
could not find implicit value for parameter p: shapeless.ops.hlist.Prepend[In,shapeless.::[A,shapeless.HNil]]
How do I write a function that returns the result of as, and what is its signature?
Thanks!
As you explain correctly, the reason we use prepend is to keep the types of the steps labelled with as. It's keeping them in the reverse order since it's easier to process on both sides: for capturing and replaying.
So the implicit p: Prepend[Labels, End :: HNil] is prepending the type at the current step so that we have it captured in the second type parameter (and can use it in later steps, e.g. select).
As far as I can see you're doing exactly the right thing, and it actually works... for me anyway :)
This compiles:
import gremlin.scala._
import shapeless.{HNil, ::}
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory
def graph = TinkerFactory.createModern.asScala
val gs1: GremlinScala[Vertex, Vertex :: HNil] = graph.V().as("a")
val gs2: GremlinScala[Vertex, Vertex :: HNil] = AsOperation("someLabel").operate(graph.V())

How to sum up all nodes in this scala fold_tree function

I am a beginner with scala. I have been given a fold_tree_preorder function that implements the higher order function fold on a binary tree. The tree, node and leaf definitions are below
abstract class Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Node[A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A]
This is the function I have been given
def fold_tree_preorder [Z,A](f:(Z,A)=>Z) (z:Z) (t:Tree[A]) : Z =
t match {
case Leaf(value) => f(z, value)
case Node(value , lt, rt) => {
val z1 = f(z,value)
val z2 = fold_tree_preorder (f) (z1) (lt)
fold_tree_preorder (f) (z2) (rt)
}
}
I am not sure how to actually call this function. I am trying to do something like the following:
def count_tree [A](t:Tree[A]) : Int =
fold_tree_preorder[A,A=>A]((z,a)=>(z+a))(0)(t)
But I am getting errors like type mismatch error. I don't think the parameters themselves are correct either, but I'm not even sure how to test what the output would look like because I can't figure out the correct way of calling the fold_tree_preorder function. How can I input the correct syntax to call this function?
z is the fold_tree_preorder function is the output type you are expecting which is Int
Use the function like below
assuming that count_tree counts number of nodes of the tree
def count_tree [A](t:Tree[A]) : Int =
fold_tree_preorder[Int, A]((z,a) => z + 1 )(0)(t)
Just add 1 to the z on visiting a node to count number of nodes
def fold_tree_preorder [Z,A](f:(Z,A)=>Z) (z:Z) (t:Tree[A]) : Z
The first argument is f, is function that takes the result so far (of type Z) and the value contained in your tree A)
def count_tree [A](t:Tree[A]) : Int
In your function your promising to return an Int based on a tree of which you don't know the element type, parameterized as A. This leads you to add an Int to an A.
Summing and counting are different things, if you decide to count the number of values, you do not need to know anything about A. If you decide to sum the values, you need to know you have a + operator defined for A.
You might need to learn more about scala's types.
https://twitter.github.io/scala_school/advanced-types.html

How to understand "The variance position of a method parameter is the opposite of the variance position of the enclosing parameter clause."

I see this sentence is scala specification (pdf):
The variance position of a method parameter is the opposite of the variance position of the enclosing parameter clause.
Which is on page 44.
But I can't quite understand it. Could you give me some samples?
So, let's start with a motivating example. Suppose I write the following:
class Foo[+A] {
def foo(a : A) = ???
}
Now, by annotating the type parameter A with a +, I've declared that Foo is covariant in A, which is to say that if X <: Y, then Foo[X] <: Foo[Y]. So, suppose I have such a Foo[X] and I try to pass it to a function which requires a Foo[Y]:
def bar(a : Y, x : Foo[Y]) = {
x.foo(a)
}
Now, bar tries to call x.foo with a Y. But x is a Foo[X], and X is a subtype of Y - so it's like trying to pass an Object to a function requiring a String - there's no guarantee that the Object contains everything that's needed to do this. So the definition of Foo above is invalid - to use the terminology in the specification, the type parameter A is covariant, but you've attempted to use it in a contravariant position - as the parameter to a function.
The set of rules set out in the Scala spec where you've referenced are the rules used by the Scala compiler to determine the variance position of different places in the code, which it uses to check that you haven't done anything like the definition of Foo above. The specific clause you identify gives the rule corresponding to the example above - it says that the variance position of a parameter clause (e.g. within the parameter list of a function) is the opposite of the surrounding variance position.
Usually, this means that parameter clauses are contravariant. However, things can get multiply inverted:
class Foo[A, B] {
def foo(a : A) = {
def bar(b : B) = ???
}
}
Here, the parameter clause of foo is contravariant, and hence the parameter clause of bar is inverted again, and is covariant. So the following definition is valid:
class Foo[-A, +B] {
def foo(a : A) = {
def bar(b : B) = ???
}
}

Two sets of constructor parameters in a scala class

What does this code do? Why is there two sets of constructor parameters?
class A(val x: Int)(val y: Int)
I can initialize an object and use both fields:
val a = new A(5)(7)
println(a.x + ", " + a.y)
If I make it a case class, I can match only by the first set of parameters.
case class A(x: Int)(y: Int)
val a = A(5)(7)
a match {
A(x) => println(x)
}
It's not possible to create 3 sets of parameters. It doesn't compile. So what is the meaning of the two sets of constructor parameters?
According to the scala specification (see section 5.3), the second set of parameters is dedicated to implicit parameters. Dividing the parameters in two sets allow you to define only non-implicit paameter and let the other be contextually defined.
It is quite strange actually that the compiler accpet non-implicit parameters in the second set.