Fork me on GitHub
#fulcro
<
2018-11-02
>
tony.kay01:11:32

@pvillegas12 I have a lot to say on testing, and I’ve said it in talks and many other places…some online, some here. I personally think UI-layer testing is mostly a waste of precious developer time. Wilker’s approach is the best I’ve seen for insuring your components won’t throw exceptions when in the wild, which is mainly what you should care about…visual “jankiness” typically has: low effect on end user, is easily reported and fixed, is constantly in the developers face while developing, and any kinds of tests around them usually fail a lot more for bad reasons than useful ones. I would never pay a dev $90k+ a year to write them. I think the cost/benefit ratio is waaaay too high for all but the most sensitive scenarios (e.g. the UI having a glitch threatens someone’s life)

pvillegas1201:11:31

What about acceptance tests? Ones that exercise the entire application (both backend + frontend)?

tony.kay01:11:41

If you actually measure the time spent on those tests in real $$$ for dev costs vs. the real $$$ benefit of them (or even the $$$ risk), I think you’ll come to the same conclusion. Are you going to lose a customer over a UI glitch? How often do those glitches happen? Do they usually make the software unusable? I’ve been doing this a long time, and the answers I’ve found are: - never, unless it sucks really badly…but that isn’t fixed by tests - rarely. - rarely.

tony.kay01:11:31

Depends. If it’s a REST endpoint with clear specs, then an acceptance test is easy, cheap, and great.

tony.kay01:11:58

If you’re trying to run your UI in a full-stack deployed scenario for acceptance…never seen that pay off in automation.

tony.kay01:11:06

not even CLOSE

tony.kay01:11:36

Now, I will write a very small number of smoke tests that try to prove the system is “up”

tony.kay01:11:45

those are useful for automated monitoring

tony.kay01:11:02

and that does pay off quickly

pvillegas1201:11:22

or at least cover the major use cases

pvillegas1201:11:36

the permutations can go at the unit test level

tony.kay01:11:41

proving a system “correct” from the outside is a costly, futile effort

tony.kay01:11:03

If you’ve hit spots that exercise the major components, that’s enough

tony.kay01:11:15

got a schedule system that runs on the back-end..you need to do something that hits it

tony.kay01:11:21

yes, major system checks

tony.kay01:11:28

proving network connectivity is right, etc.

tony.kay01:11:40

but not really proving anything about the software itself…these are system integration tests

tony.kay01:11:49

“can I talk to the db?”

tony.kay01:11:02

that kidn of thing…but yes, through the UI so you know the whole stack is working

pvillegas1201:11:15

what kind of tests do you do for your components then?

tony.kay01:11:23

and for that you’re gonna need a driver that can run the thing with js etc

tony.kay01:11:31

low-level components? None.

tony.kay01:11:42

people are playing with them 24/7…

tony.kay01:11:05

they rarely if ever break, don’t cause much of a problem if they do (usually a css glitch that you can’t catch anyhow)

tony.kay01:11:11

waste of time

tony.kay01:11:32

I mean, you use the darn thing quite a bit while designing it don’t you?

tony.kay01:11:59

and if you change it in any significant way, your tests would all mostly break…

tony.kay01:11:22

But I encourage you to actually do the math..good testing is a balance of a technique that can help you, with real costs. You can get quite good coverage effectively…but don’t waste your money where it doesn’t do so

pvillegas1201:11:25

What I perceive is that I would test lower lever functions that the component uses, not particularly the dom rendering

tony.kay01:11:35

your rendering is pure

tony.kay01:11:44

if the state is right, the rendering is likely to be so as well

tony.kay01:11:20

so, if you’ve testing your state manipulations, you’re covering what really counts

tony.kay01:11:56

one of the problems with dynamic languages, though, is that you lose the connection between tests of state and the requirement of the component

tony.kay02:11:04

this is where clojure spec can help

tony.kay02:11:30

IMO if you’re going to write tests around state, then you also need specs that are checked during dev

pvillegas1202:11:30

can you explain the connection better?

tony.kay02:11:55

So, in a typed language, you might say “this UI component takes a PersonLineItem”

tony.kay02:11:06

the compiler will verify that that’s what you actually pass to it

tony.kay02:11:20

your tests on state would make up instances of PersonLineItem…they’d test what they’re putting in

tony.kay02:11:41

now the compiler and type system has checked that the two have a logical connection

tony.kay02:11:03

in languages without a static type system, you’re throwing around bags of data

tony.kay02:11:36

so your tests might prove that the person line item “map” has a :foo in it, but the component might actually want :bar

tony.kay02:11:51

they’re not logically checked for connection by a compiler

pvillegas1202:11:06

With specs you can also generate the test data

pvillegas1202:11:47

right, so you would make dev-time checks that what the component receives is correct?

tony.kay02:11:48

well, if you follow Wilker’s approach, you’d run generative tests on the UI component to the same specs your state manipulations do with it’s state

pvillegas1202:11:00

I mean, for stateful components, there is a check between query and what you destructure in props right?

tony.kay02:11:27

if you use the non-lambda version of defsc options, yes

tony.kay02:11:43

it’s not a spec check, but you can trust the query as a result of that

tony.kay02:11:53

and the query has the props you can spec

pvillegas1202:11:08

how would you run the spec at devtime?

tony.kay02:11:35

if you wanted to, you could just use (s/valid? ::spec props) in your component near the top with some kidn of logging

pvillegas1202:11:48

I encountered this with mutations, I wanted a precondition to hold (one could use spec here) but I got forced to do that in the mutation* version

tony.kay02:11:19

and if you surrond those with (when js/goog.DEBUG ...) they’ll get dropped by DCE for release builds

💯 4
pvillegas1202:11:31

This same approach applies to mutations as well? I have some mutations that use certain arguments for local changes and others for the remote

pvillegas1202:11:39

(thinking about the file upload part)

pvillegas1202:11:47

I wanted to check the required keys I wanted on the params map

wilkerlucio02:11:38

there is missing component initialization here, I omited because that requires tons os local code to reason about

wilkerlucio02:11:56

but its just about getting props from line 17 and mixing with your initial state

claudiu09:11:00

Hi, Working on a routing library for fulcro. Currently I'm adding a protocols to defsc, but thinking that it could have a nicer interface if implemented as a macro that generates the defsc macro 😅. Does anybody have some code that does something similar and could help me out with an example ? What I'm going for is something like:

claudiu09:11:03

(defsc-route MainPage [this props]
  {:query         [:prop1]
   :ident         (fn [] [:page/main :singleton]) 
   :initial-state {:prop1 true}
   :route-entered (fn [component]
                     (js/console.log "router Entered"))}
  (dom/div "Page content"))
  
  
; results in ->

(defsc MainPage [this props]
  {:query         [:prop1]
   :ident         (fn [] [:page/main :singleton]) 
   :initial-state {:prop1 true}
   :protocols     [static
                   Routing
                   (route-entered [this]
                     (js/console.log "router Entered"))]}
  (dom/div "Page content"))

pvillegas1212:11:00

@claudiu do you have anything visible yet? I would definitely like a routing library that mimics the Ember router (which has been copied in other projects, the API is quite good for major use cases). Right now there is a lot of repetition on defining routes with html5 support

claudiu14:11:21

@pvillegas12 Getting really close to something that I can share. Going for a full top level abstraction including: html5, dynamic query routing, and initial data load. Hopefully by next week should have some workable "pre-alpha" stuff ready if you want to try it out.

👍 4
tony.kay14:11:40

@claudiu so the defmutation macro is probably the easiest to read as an example…defsc itself it a very large thing because of all of the error checking and such it does…Basically, I recommend writing specs for your syntax, using those to pick the bits you want apart, and then emit a normal defsc.

tony.kay14:11:49

like you’re suggesting

tony.kay14:11:24

The defsc macro has some bits that would be useful to you, like arity-checking on the lambda form

claudiu14:11:42

@tony.kay yep love the defsc macro checking stuff. Just want to wrap it up in something that's easier on the eyes and implements the protocols stuff on top. This will be the first macro I write, was hoping somebody did something similar and I can just copy/paste adjust and continue on the other parts of my mini project. 🙂 Will take a look at defmutation 🙂

tony.kay14:11:46

The build-ident helper does the morphing of the :ident option…it’s probably the simplest

tony.kay14:11:41

actually, since you’re trying to add an option that turns into a protocol…there’s a nice generality there that might be useful for others

tony.kay14:11:08

we could probably build a macro called something like extend-defsc that could be used to create a macro that does this transform

claudiu14:11:01

yep. Think I need to add more than 1 protocol actually 😞 Since I want to add optional methods and looks like in cljs there is no nice way to check if a method of a protocol is implemented. Need to look at it a bit more but last time I could not find a nice way to do that

claudiu14:11:10

that sounds like a really useful macro to have 🙂 will give it a shot

tony.kay14:11:11

I can throw a quick example together and perhaps you can refine it?

tony.kay14:11:46

seems like a good one for incubator

tony.kay14:11:17

fork incubator and I’ll add a starting point in the feature/extend-defsc branch

claudiu14:11:03

awesome 🙂 thank you 🙂

tony.kay16:11:13

@claudiu https://youtu.be/mXcxTQnwIM4 should be up in 2-3 minutes…part one of a macro tutorial

bananadance 4
👍 4
claudiu16:11:29

Awesome. Watching it now. Thank you :)

tony.kay20:11:15

Part 2 is coming @claudiu. I ended up with a fully-working macro, spent more time than I had, though…but at least we have some macro videos to help others now.