Fork me on GitHub
#code-reviews
<
2019-05-07
>
Jakub Holý (HolyJak)09:05:36

Hello, I would really appreciate feedback on my API design. I am integrating with a Java test framework that requires that I pass it an object with user-determined methods (used via reflection; there is no interface defining them). I also want to be able to supply options to the test framework. This is a macro (wrapping gen-class & more) that I came up with to do this:

(deffixture
  "math.algebra.AdditionFixture"
  [add subtract]  ;; expose these two functions as methods on the class instances 
  {:concordion/full-ognl                    false  ;; some options for the test framework, optional
   :concordion/fail-fast-exceptions        [IndexOutOfBoundsException]
   ::before-suite                          #(println "AdditionFixture: I run before each Suite")  ;; setup & teardown functions, optional
   ::before-spec                           #(println "AdditionFixture: I run before each Spec")
   ::before-example                        #(println "AdditionFixture: I run before each example")
   ::after-example                         #(println "AdditionFixture: I run after each example")
   ::after-spec                            #(println "AdditionFixture: I run after each Spec")
   ::after-suite                           #(println "AdditionFixture: I run after each Suite")})
I am especially unsure about the setup/teardown functions. Perhaps I should instead pass them along with the methods, relying on well-known names, i.e. [add subtract beforeSuite ... afterSuite]? Thoughts? (You can see the code here https://github.com/holyjak/clj-concordion/blob/0.0.3/src/clj_concordion/core.clj#L234 - it does gen-class, defn for each of the methods, deftest so that we can run it via clojure.test, and adds an _opts method to the class for passing the options map around)

noisesmith17:05:14

I assume you need gen-class instead of proxy because you need to be able to refer to the class by name, as well as extending a concrete base class?

noisesmith18:05:11

@holyjak what would it look like if you used proxy and deftype instead of genclass? is there something that definitely wouldn't work?

Jakub Holý (HolyJak)21:05:23

I need to add custom methods, not described by any interface. The only construct that supports that is gen-class, I believe?