Using a HavePropertyMatcher for collection elements in ScalaTest? - unit-testing

I've been using ScalaTest's FeatureSpec for a couple of days now and I'm trying to understand if it's possible to define the following spec using the built-in matchers (and if not, how I can write a suitable custom matcher).
Suppose I have the class Book:
case class Book(val title: String, val author: String)
and in my test I have a List of books:
val books = List(Book("Moby Dick", "Melville"))
Now, I would like to specify that the books list should contain a book with the title "Moby Dick". I would like to write something like:
books should contain (value with title "Moby Dick")
I can't seem to figure out from the docs and code if it's possible to express this requirement in ScalaTest. Has anyone ran into a similar situation?

In the meantime here's a custom matcher you can use:
def containElement[T](right: Matcher[T]) = new Matcher[Seq[T]] {
def apply(left: Seq[T]) = {
val matchResults = left map right
MatchResult(
matchResults.find(_.matches) != None,
matchResults.map(_.failureMessage).mkString(" and "),
matchResults.map(_.negatedFailureMessage).mkString(" and ")
)
}
}
Then you can use the full power of the ScalaTest Have matcher to inspect the fields of your object:
val books = List(Book("Moby Dick", "Melville"),
Book("Billy Budd", "Melville"),
Book("War and Peace", "Tolstoy"))
books should containElement(have('title("Moby Dick")))
books should containElement(have('title("Billy Budd"), 'author("Melville")))
books should containElement(have('title("War and Peace"), 'author("Melville")))
The last one is a failure producing this output:
The title property had value "Moby Dick", instead of its expected value "War and Peace", on object Book(Moby Dick,Melville) and The title property had value "Billy Budd", instead of its expected value "War and Peace", on object Book(Billy Budd,Melville) and The author property had value "Tolstoy", instead of its expected value "Melville", on object Book(War and Peace,Tolstoy)
You can also combine matchers with and or or, use not, etc.

Not currently, though you will be able to do something like this very soon in the future. What you can do now is something like:
books.exists(_.title == "Moby Dick") should be (true)

Related

how can I use the copy method for case classes on a list of that case class?

I have a list of records (record is a case class). I am trying to simultaneously update all of the records in the list (using the copy function) and return a list of the updated records.
I tried to use a foreach method but it's not allowing me to produce the list as a result.
This is what I tried so far, I'm not sure if any of this is right
def update_record(record: List[Rec]): List[Rec] = {
val result = record.foreach(r => {
r.copy(firstname = get_firstname(r, record), lastname = get_lastname(r, record))
})
result
}
but result doesn't produce a list so I'm not sure what to do now.
You just need to use map instead of foreach.
def update_record(record: List[Rec]: List[Rec] =
record.map { r =>
r.copy(firstname = get_firstname(r, record), lastname = get_lastname(r, record))
}
Anyways, it would be good to follow some tutorial or course or read a book about the language. This is just basic knowledge of the standard library.
Some links that may be useful:
Scala tour.
Scala book.
Scaladoc.
Scala style guide.

Groovy: Accessing class fields via list

First, I'm sorry for asking such a dumb question, but quick googling didn't help me much...
I'm a Java delevoper and very new to Groovy. Consider the following code snippet:
class Person {
public String name
}
​def jack = new Person()
jack.name = "Jack"
​
def bob = new Person()
bob.name = "Bob"
def list = new java.util.ArrayList()
list.add(jack)
list.add(bob)
println list.name​
Executing it gives the following output (list of name field values for each Person in the list):
[Jack, Bob]
So my question is what the corresponding java code for calling list.name?
My assumption is that it translates to something like:
list.stream().map(person -> person.name).collect(Collectors.toList())
Can somebody explain what exactly happens when i call list.name?
Thanks in advance!
Your code
list.property
is the shortest way to write this. What groovy implies here is the use of the spread operator:
list*.property
(note the * there). And .property could be short here for .getProperty(), for an implicit call to the getter).
So your assumption is correct, that this is the eager collection of the values .getProperty() returns into an ArrayList.

Tkinter Input Substitutions

I've been working on a text based game in Tkinter, and I need a way so as to allow more flexibility with input. Basically, what I'm looking for is how to code:
if Input.get() == "look at" Item:
Item.look()
But with the flexibility of 'item' being a class, with subclasses, all of which can be 'looked at'. This is my current (non-working) code for this segment:
def Check():
if Output == "look at" Item:
Item.look()
else:
pass
class Item():
def __init__(self, name, description, value, quantity):
self.name = name
self.description = description
self.value = value
def look(self):
Look.Title = "{}".format(self.name)
Look.Description = "{}".format(self.Description)
Look.Value = "{} is worth {}.".format(self.name, self.value)
Details.insert(Look.Title)
Details.insert(Look.Description)
Details.insert(Look.Value)
Details.insert(Look.Quantity)
class Headphones(Item):
def __init__(self):
super.__init__(name = "Headphones", description = "A set of high quality white headphones.", value = 150)
Any help is much appreciated,
Blaze
You will need to do some sort of mapping between the input and the functions you want to call. You will need to parse the string in order to pull out the object from the input string and use the result of the parsing to look up the proper object or class.
For example, you could use a regular expression to parse the string "look at X", and then use "X" as an index into a dictionary in order to know what class to instantiate.
Here's a simple example:
import re
class Headphones(object):
def look(self):
print("you are looking at headphones")
class Goggles(object):
def look(self):
print("you are looking at goggles")
class Unknown(object):
def look(self):
print("I don't know what you're looking at")
def check(input):
map = {
"goggles": Goggles,
"headphones": Headphones,
}
match = re.match(r'look at (.*)', input)
if match:
thing = match.group(1)
cls = map.get(thing, Unknown)
object = cls()
object.look()
for phrase in ("look at headphones",
"look at goggles",
"look at something else"):
check(phrase)
Note: this is one of many ways to solve the problem. The point is, you need to:
write a parser that can pull out the important parts from the input, and
use the result of the parsing stage to decide how to process the data
The parser can be anything from simply splitting the input on spaces and grabbing the last word, to using a regular expression, to using a full blown parser using something like pyparsing.

Django get_FOO_display and distinct()

I've seen answers to both halves of my question, but I can't work out how to marry the two.
I have a book model, and a translatedBook model.
The translatedBook has a langage set up as model choices in the usual way:
LANGUAGES = (
(u'it', u'Italian'),
(u'ja', u'Japanese'),
(u'es', u'Spanish'),
(u'zh-cn', u'Simplified Chinese'),
(u'zh-tw', u'Traditional Chinese'),
(u'fr', u'French'),
(u'el', u'Greek'),
(u'ar', u'Arabic'),
(u'bg', u'Bulgarian'),
(u'bn', u'Bengali'),
etc
I know that to get "Italian" I have to do translatedBook.get_language_display on a Book object.
But how do I get a list of distinct languages in their long format?
I've tried:
lang_avail = TargetText.objects.values('language').distinct().order_by('language')
lang_avail = TargetText.objects.distinct().order_by('language').values('language').
lang_avail = TargetText.objects.all().distinct('language').order_by('language')
but I can't seem to get what I want - which is a list like:
"English, Italian, Simplified Chinese, Spanish"
The final lang_avail listed above didn't return the list of 5, it returned the list of 355 (ie, # of books) with multiple repeats....
-- EDIT --
Daniel's answer almost got me there - as it turns out, that throws a "dicts are unhashable" error. Thanks to Axiak on the django irc, we use Daniel's solution with this line instead:
langs = TargetText.objects.values_list('language', flat=True).distinct().order_by('language')
and it works.
There isn't a built-in way. You could do something like this:
lang_dict = dict(LANGUAGES)
langs = TargetText.objects.values('language').distinct().order_by('language')
long_langs = [lang_dict[lang] for lang in langs]
which simply makes a dictionary out of the LANGUAGE choices and then looks up each language ID.

What is simplest way join __contains and __in?

I am doing tag search function, user could observe a lot of tags, I get it all in one tuple, and now I would like to find all text which include at least one tag from the list.
Symbolic: text__contains__in=('asd','dsa')
My only idea is do loop e.g.:
q = text.objects.all()
for t in tag_tuple:
q.filter(data__contains=t)
For example:
input tuple of tags, ('car', 'cat', 'cinema')
output all messages what contains at least one word from that tuple, so My cat is in the car , cat is not allowed in the cinema, i will drive my car to the cinema
Thanks for help!
Here you go:
filter = Q()
for t in tag_tuple:
filter = filter | Q(data__contains=t)
return text.objects.filter(filter)
A couple of tips:
You should be naming your model classes with a capital (i.e. Text, not text)
You may want __icontains instead if you're not worried about the case
I don't know Django, so I have no idea how to apply this filter, but it seems you want a function like this one:
def contains_one_of(tags, text):
text = text.split() # tags should match complete words, not partial words
return any(t in text for t in tags)