How to correctly define a fabricator that ex_machina's `params_for` recognises? - testing

I started on a test that should verify that the fabricated objects are valid.
But even though I have defined a practitioner_factory, it does not find it.
Any idea why?
practitioner_factory! works when I manually run it from iex.
1 defmodule Booking.PractitionersTest do
2 use ExUnit.Case, async: true
3 use Booking.DataCase
4 use ExMachina.Ecto
5 alias Ecto.Changeset
6 alias Booking.Factory
7
22 test "is valid from the factory" do
23 new_practitioner = params_for(:practitioner)
24 changeset = Practitioner.changeset(Practitioner, new_practitioner)
25 assert changeset.valid?
26 end
It crashes with the following stack trace:
1) test practitioners is valid from the factory (Booking.PractitionersTest)
test/booking/practitioners_test.exs:22
** (ExMachina.UndefinedFactoryError) No factory defined for :practitioner.
Please check for typos or define your factory:
def practitioner_factory do
...
end
code: new_practitioner = params_for(:practitioner)
stacktrace:
(ex_machina 2.7.0) lib/ex_machina.ex:243: ExMachina.build/3
(ex_machina 2.7.0) lib/ex_machina/ecto.ex:127: ExMachina.Ecto.params_for/3
test/booking/practitioners_test.exs:23: (test)
Here's my lib/booking/factory.ex
1 defmodule Booking.Factory do
2 # with Ecto
3 use ExMachina.Ecto, repo: Booking.Repo
4
5 alias Booking.Practitioners.Practitioner
6 alias Booking.Products.Product
7 alias Booking.Repo
8
9 def practitioner_factory do
10 %Practitioner{
11 first_name: Faker.Person.first_name(),
12 last_name: Faker.Person.last_name()
13 }
14 end
23 def practitioner_factory! do
24 practitioner_factory()
25 |> Repo.insert()
26 end

Looking at the path where you have defined the factory it looks like it's not in the test folder. If you don't need to use the factory in other environments, you can add it inside test/support so that it is only compiled in the test environment.
Also, be sure to start the application in your test/test_helper.exs before ExUnit.start, using:
{:ok, _} = Application.ensure_all_started(:ex_machina)
Looking at your test file, you have:
1 defmodule Booking.PractitionersTest do
2 use ExUnit.Case, async: true
3 use Booking.DataCase
4 use ExMachina.Ecto
5 alias Ecto.Changeset
6 alias Booking.Factory
...
23 new_practitioner = params_for(:practitioner)
As you're not doing something like Factory.params_for(:practitioner) (from the alias Booking.Factory), you need to do something like import Booking.Factory in line 6, otherwise that factory is not defined in your test file.
Also, you probably don't need line 4 use ExMachina.Ecto as that is already defined in line 3 of lib/booking/factory.ex.

Related

how to convert function output into list, dict or as data frame?

My issue is, i don't know how to use the output of a function properly. The output contains multiple lines (j = column , i = testresult)
I want to use the output for some other rules in other functions. (eg. if (i) testresult > 5 then something)
I have a function with two loops. The function goes threw every column and test something. This works fine.
def test():
scope = range(10)
scope2 = range(len(df1.columns))
for (j) in scope2:
for (i) in scope:
if df1.iloc[:,[j]].shift(i).loc[selected_week].item() > df1.iloc[:,[j]].shift(i+1).loc[selected_week].item():
i + 1
else:
print(j,i)
break
Output:
test()
1 0
2 3
3 3
4 1
5 0
6 6
7 0
8 1
9 0
10 1
11 1
12 0
13 0
14 0
15 0
I tried to convert it to list, dataframe etc. However, i miss something here.
What is the best way for that?
Thank you!
A fix of your code would be:
def test():
out = []
scope = range(10)
scope2 = range(len(df1.columns))
for j in scope2:
for i in scope:
if df1.iloc[:,[j]].shift(i).loc[selected_week].item() <= df1.iloc[:,[j]].shift(i+1).loc[selected_week].item():
out.append([i, j])
return pd.DataFrame(out)
out = test()
But you probably don't want to use loops as it's slow, please clarify what is your input with a minimal reproducible example and what you are trying to achieve (expected output and logic), we can probably make it a vectorized solution.

How to convert Stack based instructions to Register based

This is what I have tested with the dis module in python -
>>> def f():
... a = 1
... b = 2
... c = 3
... a = b + c * a
... return a + c
...
>>> dis.dis(f)
2 0 LOAD_CONST 1 (1)
2 STORE_FAST 0 (a)
3 4 LOAD_CONST 2 (2)
6 STORE_FAST 1 (b)
4 8 LOAD_CONST 3 (3)
10 STORE_FAST 2 (c)
5 12 LOAD_FAST 1 (b)
14 LOAD_FAST 2 (c)
16 LOAD_FAST 0 (a)
18 BINARY_MULTIPLY
20 BINARY_ADD
22 STORE_FAST 0 (a)
6 24 LOAD_FAST 0 (a)
26 LOAD_FAST 2 (c)
28 BINARY_ADD
30 RETURN_VALUE
Those are instructions for a stack-based virtual machine. Is there any way to convert the above stack-based instructions into register-based instructions provided I have access to unlimited number of registers.
I only know about one tool which does that, we know that JVM is stack based but Dalvik VM is register-based. When we write code in Java, the class files contain stack based instructions and the dx tool converts the stack based instructions to register based instructions so that it can run in the Dalvik VM. So most probably there could be an algorithm somewhere which I have missed.
Also can there be an edge can where the stack could dynamically grow and shrink(which would be decided in runtime) , in that case it would be impossible to convert stack based instructions to register based. However one tool does it.
Can someone point me to the correct direction. Or know any algorithm which can help in this.

How can I export parameter from excel to games?

How can I export data from Excel to GAMS? I have a set i and parameter b(i).
b(0)= 30,...,b(10)=18 are:
0 30
1 17
2 21
3 32
4 19
5 29
6 24
7 20
8 23
9 27
10 18
I have an Excel file with name "Book1", my code results in ERROR 409:
Unrecognizable item - skip to find a new statement
looking for a ';' or a key word to get started again
Why? What can I do? This is my code:
set i/1*10/
parameter b(i)
$call =xls2gms r=sheet2!B3:C13 i=Book1.xlsx o=set.inc
$include set.inc
;
You need to add semicolons after each command. The only exception are the $ commands compile time commands. Fx:
set i /1*10/;
parameter b(i);
$call =xls2gms r=sheet2!B3:C13 i=Book1.xlsx o=set.inc
$include set.inc

How to output data with Hive-style directory structure in Scalding?

We are using Scalding to do ETL and generate the output as a Hive table with partitions. Consequently, we want the directory names for partitions to be something like "state=CA" for example. We are using TemplatedTsv as follows:
pipe
// some other ETL
.map('STATE -> 'hdfs_state) { state: Int => "State=" + state }
.groupBy('hdfs_state) { _.pass }
.write(TemplatedTsv(baseOutputPath, "%s", 'hdfs_state,
writeHeader = false,
sinkMode = SinkMode.UPDATE,
fields = ('all except 'hdfs_state)))
We adopt the code sample from How to bucket outputs in Scalding.
Here are two issues we have:
except can't be resolved by IntelliJ: Am I missing some imports? We don't want to explicitly enter all the fields within the "fields = ()" statement as fields are derived from the code inside the groupBy statement. If entering explicitly, they could be easily out of sync.
This approach looks too hacky as we are creating an extra column so that the directory names can be processed by Hive/Hcatalog. We are wondering what should be the right way to accomplish it?
Many thanks!
Sorry previous example was a pseudocode. Below I will give a small code with input data example.
Please note that this only works with Scalding version 0.12.0 or above
Let's image we have input as below which define some purchase data,
user1 1384034400 6 75
user1 1384038000 6 175
user2 1383984000 48 3
user3 1383958800 48 281
user3 1384027200 9 7
user3 1384027200 9 11
user4 1383955200 37 705
user4 1383955200 37 15
user4 1383969600 36 41
user4 1383969600 36 21
Tab separated and the 3rd column is a State number. Here we have integer but for string based States you can easily adapt.
This code will read the input and put them in 'State=stateid' output folder buckets.
class TemplatedTsvExample(args: Args) extends Job(args) {
val purchasesPath = args("purchases")
val outputPath = args("output")
// defines both input & output schema, you can also make separate for each of them
val ioSchema = ('USERID, 'TIMESTAMP, 'STATE, 'PURCHASE)
val Purchases =
Tsv(purchasesPath, ioSchema)
.read
.map('STATE -> 'STATENAME) { state: Int => "State=" + state } // here you can make necessary changes
.groupBy('STATENAME) { _.pass } // this is optional
.write(TemplatedTsv(outputPath, "%s", 'STATENAME, false, SinkMode.REPLACE, ioSchema))
}
I hope this is helpful. Please ask me if anything is not clear.
You can find full code here.

creating a variable that change sizes in for loop

I have to create a fits file using the data from two IDL structures. This is not the basic problem.
My problem is that first I have to create a variable that contains the two structures.
To create this I used a for loop that will write at each step a new row of my variable.
The problem is that I cannot add the new row at the next step, it overwrite it so at the end my fits file instead of having, I don't know, 10000 rows, it has only one row.
This is what I also tried
for jj=0,h[1]-1 do begin
test[*,jj] = [sme.wave[jj], sme.smod[jj]]
print,test
endfor
but the * wildcard is messing up everything because now inside test I have the number corresponding to jj, not the values of sme.wave and sme.smod.
I hope that someone can understand what I asked and that can help me!
thank you in advance!
Chiara
Assuming your "sme.wave" and "sme.smod" structure fields contain 1-D arrays with the same number of elements as there are rows in "test", then your code should work. For example, I tried this and got the following output:
IDL> test = intarr(2, 10) ; all zeros
IDL> sme = {wave:indgen(10), smod:indgen(10)*2}
IDL> for jj=0, 9 do test[*,jj] = [sme.wave[jj], sme.smod[jj]]
IDL> print, test
0 0
1 2
2 4
3 6
4 8
5 10
6 12
7 14
8 16
9 18
However, for better speed optimization, you should instead do the following and take advantage of IDL's multi-threaded array operations. Looping is typically much slower than something like the following:
IDL> test = intarr(2, 10) ; all zeros
IDL> sme = {wave:indgen(10), smod:indgen(10)*2}
IDL> test[0,*] = sme.wave
IDL> test[1,*] = sme.smod
IDL> print, test
0 0
1 2
2 4
3 6
4 8
5 10
6 12
7 14
8 16
9 18
Further, if you don't know what the size of "test" is ahead of time, and you want to append to the variable, i.e. add a row, then you can do this:
IDL> test = []
IDL> sme = {wave:Indgen(10), smod:Indgen(10)*2}
IDL> for jj=0, 9 do test = [[test], [sme.wave[jj], sme.smod[jj]]]
IDL> Print, test
0 0
1 2
2 4
3 6
4 8
5 10
6 12
7 14
8 16
9 18