Try changing your JSON tree to this :-

Users:
  - uid
     - email

tests
  - noOfTotalTest : 4 // Lets say 4
  - id
     - title
     - user_uid
     - index   // Just index of the post

Now use this codeBlock :-

    FIRDatabase.database().reference().child("tests/noOfTotalTest").observeSingleEvent(of: .value, with: {(Snap) in


        let totalNoOfTest = Snap.value as! Int
        print(totalNoOfTest)
        let randNum = Int(arc4random_uniform(UInt32(totalNoOfTest))) + 1
        print(randNum)
        FIRDatabase.database().reference().child("tests").queryOrdered(byChild: "index").queryEqual(toValue: randNum).observeSingleEvent(of: .value, with: {(Snapshot) in

            print(Snapshot.value!)

        })
    })

NoW whenever you post a test to your database you gotta do these things:-

  • Query for the total no of tests in the DB, noOfTotalTest
  • Once retrieved increment it by +1 and update noOfTotalTest and put it in with other of the test details and set it to your DB
  • And the process carries on....

PS:- For making the post just/ SAVING:-

  FIRDatabase.database().reference().child("tests/noOfTotalTest").observeSingleEvent(of: .value, with: {(Snap) in 

if Snap.exists(){

            // This is not the first post

            let totalNoOfTest = Snap.value as! Int

            FIRDatabase.database().reference().child("tests").childByAutoId().setValue(["userID" : UID, "details" : Details, "index" : totalNoOfTest + 1])
   FIRDatabase.database().reference().child("tests/noOfTotalTest").setValue(totalNoOfTest + 1)
        } else {

         // This is your first post

         FIRDatabase.database().reference().child("tests").childByAutoId().setValue(["userID" : UID, "details" : Details, "index" : 1])
   FIRDatabase.database().reference().child("tests/noOfTotalTest").setValue(1)  

        }

})

To extend this for you to be able to delete, you can save the indexes that are active in your node's which you need to randomise.

For that add this to your JSON tree:-

active_Indexes :{

   12 : true,
   09 : true,
   198 : true,
   11: true,
   103 : true,
  }

Now what you need is to store these INDEX in an dictionary , then randomise the array element :-

 var localIndexDirectory = [Int : Bool]

 //Listen to any changes to the database, and update your local index directory accordingly 


override func viewDidLoad() {
    super.viewDidLoad()


    FIRDatabase.database().reference().child("active_Index").observe(.childRemoved, with: {(Snap) in

        print(Snap.value)
        let keyToBeChanged = Int(Snap.key)!
        self.localIndexDirectory.removeValue(forKey: keyToBeChanged)
        print(self.localIndexDirectory)

    })

    FIRDatabase.database().reference().child("active_Index").observe(.childAdded, with: {(Snap) in

        print(Snap)
        let keyToBeChanged = Int(Snap.key)!
        self.localIndexDirectory.updateValue(true, forKey: keyToBeChanged)
        print(self.localIndexDirectory)

    })
}

This will keep your directory updated for the indexes available(SINCE .observe is a continuos thread in your network thread) in your database, then all you need is to randomise those indexes at that particular time and query that test for that particular index. But now to activate the Deleting function in your app you also need to modify your saving function i.e whenever you save a new node to your database, make sure you also append the active_Indexes node in your DB, with that particular index.

PPS:- You would also need to update your security rules for dealing with different authentication states.